Folia Support?

This commit is contained in:
SuperRonanCraft
2023-04-19 00:00:21 -04:00
parent 5aad2125d3
commit 033eaeecdc
22 changed files with 122 additions and 61 deletions

View File

@@ -1,5 +1,6 @@
package me.SuperRonanCraft.BetterRTP;
import com.tcoded.folialib.FoliaLib;
import lombok.Getter;
import me.SuperRonanCraft.BetterRTP.player.PlayerInfo;
import me.SuperRonanCraft.BetterRTP.player.commands.Commands;
@@ -48,6 +49,7 @@ public class BetterRTP extends JavaPlugin {
//@Getter private BukkitAudiences adventure;
@Getter private boolean PlaceholderAPI;
@Getter private final RTPLogger rtpLogger = new RTPLogger();
@Getter FoliaLib folia = new FoliaLib(this);
@Override
public void onEnable() {

View File

@@ -5,6 +5,7 @@ import me.SuperRonanCraft.BetterRTP.player.commands.RTPCommand;
import me.SuperRonanCraft.BetterRTP.player.rtp.RTPSetupInformation;
import me.SuperRonanCraft.BetterRTP.references.PermissionNode;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseHandler;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.helpers.HelperRTP;
import me.SuperRonanCraft.BetterRTP.references.messages.Message;
import me.SuperRonanCraft.BetterRTP.references.messages.Message_RTP;
@@ -43,7 +44,7 @@ public class CmdQueue implements RTPCommand {
Player p = (Player) sendi;
//sendi.sendMessage("Loading...");
World world = args.length > 1 ? Bukkit.getWorld(args[1]) : null;
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
if (world != null) {
sendInfo(sendi, queueGetWorld(p, world), label, args);
} else

View File

@@ -4,6 +4,7 @@ import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.player.rtp.RTP_TYPE;
import me.SuperRonanCraft.BetterRTP.references.PermissionNode;
import me.SuperRonanCraft.BetterRTP.references.file.FileOther;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.messages.Message_RTP;
import me.SuperRonanCraft.BetterRTP.references.web.Updater;
import me.SuperRonanCraft.BetterRTP.references.helpers.HelperRTP;
@@ -16,7 +17,7 @@ public class Join {
static void event(PlayerJoinEvent e) {
Player p = e.getPlayer();
updater(p);
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
getPl().getCooldowns().loadPlayer(p);
});
rtpOnFirstJoin(p);

View File

@@ -1,7 +1,9 @@
package me.SuperRonanCraft.BetterRTP.player.rtp;
import com.tcoded.folialib.wrapper.WrappedTask;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.customEvents.RTP_CancelledEvent;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -10,9 +12,12 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.concurrent.TimeUnit;
class RTPDelay implements Listener {
private int run;
private WrappedTask task;
private final boolean cancelOnMove, cancelOnDamage;
private final RTPPlayer rtp;
@@ -25,7 +30,7 @@ class RTPDelay implements Listener {
private void delay(CommandSender sendi, int delay) {
if (!getPl().getRTP().getTeleport().beforeTeleportDelay(rtp.getPlayer(), delay)) {
run = Bukkit.getScheduler().scheduleSyncDelayedTask(BetterRTP.getInstance(), run(sendi, this), delay * 20L);
task = FoliaHelper.get().runLater(run(sendi, this), (delay * 20L) * 50L, TimeUnit.MILLISECONDS);
if (cancelOnMove || cancelOnDamage)
Bukkit.getPluginManager().registerEvents(this, BetterRTP.getInstance());
}
@@ -56,22 +61,23 @@ class RTPDelay implements Listener {
}
private void cancel() {
Bukkit.getScheduler().cancelTask(run);
if (!Bukkit.getScheduler().isCurrentlyRunning(run)) {
HandlerList.unregisterAll(this);
getPl().getRTP().getTeleport().cancelledTeleport(rtp.getPlayer());
//getPl().getEco().unCharge(rtp.getPlayer(), rtp.pWorld);
getPl().getCooldowns().removeCooldown(rtp.getPlayer(), rtp.worldPlayer.getWorld());
getPl().getpInfo().getRtping().put(rtp.getPlayer(), false);
Bukkit.getServer().getPluginManager().callEvent(new RTP_CancelledEvent(rtp.getPlayer()));
}
if (task != null)
task.cancel();
HandlerList.unregisterAll(this);
getPl().getRTP().getTeleport().cancelledTeleport(rtp.getPlayer());
//getPl().getEco().unCharge(rtp.getPlayer(), rtp.pWorld);
getPl().getCooldowns().removeCooldown(rtp.getPlayer(), rtp.worldPlayer.getWorld());
getPl().getpInfo().getRtping().put(rtp.getPlayer(), false);
Bukkit.getServer().getPluginManager().callEvent(new RTP_CancelledEvent(rtp.getPlayer()));
}
private Runnable run(final CommandSender sendi, final RTPDelay cls) {
return () -> {
private BukkitRunnable run(final CommandSender sendi, final RTPDelay cls) {
return new BukkitRunnable() {
@Override public void run() {
HandlerList.unregisterAll(cls);
if (getPl().getpInfo().getRtping().containsKey(rtp.getPlayer()))
rtp.randomlyTeleport(sendi);
}
};
}

View File

@@ -1,9 +1,11 @@
package me.SuperRonanCraft.BetterRTP.player.rtp;
import com.tcoded.folialib.FoliaLib;
import io.papermc.lib.PaperLib;
import lombok.Getter;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.customEvents.RTP_FindLocationEvent;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueData;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueHandler;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.RandomLocation;
@@ -47,7 +49,7 @@ public class RTPPlayer {
attempts++;
return;
}
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
Location loc;
if (event.getLocation() != null) // && WorldPlayer.checkIsValid(event.getLocation(), pWorld))
loc = event.getLocation();
@@ -61,7 +63,7 @@ public class RTPPlayer {
}
attempts++; //Add an attempt
//Load chunk and find out if safe location (asynchronously)
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runNextTick(() -> {
try { //Prior to 1.12 this async chunk will NOT work
CompletableFuture<Chunk> chunk = PaperLib.getChunkAtAsync(loc);
chunk.thenAccept(result -> {
@@ -89,7 +91,7 @@ public class RTPPlayer {
if (getPl().getEco().charge(player, worldPlayer)) {
tpLoc.setYaw(player.getLocation().getYaw());
tpLoc.setPitch(player.getLocation().getPitch());
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () ->
FoliaHelper.get().runNextTick(() ->
settings.teleport.sendPlayer(sendi, player, tpLoc, worldPlayer, attempts, type));
}
} else {

View File

@@ -28,8 +28,6 @@ public class RTPTeleport {
private final RTPEffects effects = new RTPEffects();
//public HashMap<Player, List<CompletableFuture<Chunk>>> playerLoads = new HashMap<>();
void load() {
effects.load();
}
@@ -71,9 +69,6 @@ public class RTPTeleport {
getPl().getpInfo().getRtping().remove(p); //No longer rtp'ing (errored)
e.printStackTrace();
}
// }
// }.runTask(getPl());
//});
}
//Effects

View File

@@ -2,6 +2,7 @@ package me.SuperRonanCraft.BetterRTP.player.rtp.effects;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.file.FileOther;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@@ -70,7 +71,7 @@ public class RTPEffect_Particles {
public void display(Player p) {
if (!enabled) return;
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
try { //Incase the library errors out
switch (shape) {
case "TELEPORT":

View File

@@ -3,6 +3,7 @@ package me.SuperRonanCraft.BetterRTP.references.database;
import lombok.Getter;
import lombok.NonNull;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.player.playerdata.PlayerData;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueData;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueGenerator;
@@ -53,7 +54,7 @@ public class DatabaseChunkData extends SQLite {
public void addChunk(Chunk chunk, int maxy, Biome biome) {
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
String pre = "INSERT OR REPLACE INTO ";
String sql = pre + tables.get(0) + " ("
+ COLUMNS.WORLD.name + ", "

View File

@@ -2,6 +2,7 @@ package me.SuperRonanCraft.BetterRTP.references.database;
import lombok.Getter;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.RandomLocation;
import org.bukkit.Bukkit;
@@ -13,7 +14,7 @@ public class DatabaseHandler {
@Getter private final DatabaseChunkData databaseChunks = new DatabaseChunkData();
public void load() {
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
databasePlayers.load();
databaseCooldowns.load();
databaseQueue.load();

View File

@@ -5,6 +5,7 @@ import lombok.NonNull;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueData;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueGenerator;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueHandler;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.worlds.RTPWorld;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -76,6 +77,11 @@ public class DatabaseQueue extends SQLite {
return queueDataList;
}*/
@Override public void load() {
if (QueueHandler.isEnabled())
super.load();
}
public List<QueueData> getInRange(QueueRangeData range) {
Connection conn = null;
PreparedStatement ps = null;

View File

@@ -3,6 +3,7 @@ package me.SuperRonanCraft.BetterRTP.references.database;
import lombok.Getter;
import lombok.NonNull;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.QueueHandler;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.RandomLocation;
import org.bukkit.Bukkit;
@@ -58,10 +59,9 @@ public abstract class SQLite {
}
public void load() {
if (!QueueHandler.isEnabled()) return;
loaded = false;
tables = getTables();
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
Connection connection = getSQLConnection();
try {
Statement s = connection.createStatement();

View File

@@ -0,0 +1,13 @@
package me.SuperRonanCraft.BetterRTP.references.helpers;
import com.tcoded.folialib.FoliaLib;
import com.tcoded.folialib.impl.ServerImplementation;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
public class FoliaHelper {
public static ServerImplementation get() {
return BetterRTP.getInstance().getFolia().getImpl();
}
}

View File

@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableCollection;
import lombok.NonNull;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.file.FileData;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.messages.placeholder.PlaceholderAnalyzer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -23,25 +24,25 @@ public interface Message {
static void sms(Message messenger, CommandSender sendi, String msg) {
if (!msg.isEmpty())
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () ->
FoliaHelper.get().runNextTick(() ->
sendi.sendMessage(placeholder(sendi, getPrefix(messenger) + msg)));
}
static void sms(Message messenger, CommandSender sendi, String msg, Object placeholderInfo) {
if (!msg.isEmpty())
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () ->
FoliaHelper.get().runNextTick(() ->
sendi.sendMessage(Objects.requireNonNull(placeholder(sendi, getPrefix(messenger) + msg, placeholderInfo))));
}
static void sms(Message messenger, CommandSender sendi, String msg, List<Object> placeholderInfo) {
if (!msg.isEmpty())
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () ->
FoliaHelper.get().runNextTick(() ->
sendi.sendMessage(placeholder(sendi, getPrefix(messenger) + msg, placeholderInfo)));
}
static void sms(CommandSender sendi, List<String> msg, Object placeholderInfo) {
if (msg != null && !msg.isEmpty()) {
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runNextTick(() -> {
msg.forEach(str -> msg.set(msg.indexOf(str), placeholder(sendi, str, placeholderInfo)));
sendi.sendMessage(msg.toArray(new String[0]));
});

View File

@@ -6,6 +6,7 @@ import me.SuperRonanCraft.BetterRTP.references.PermissionNode;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseCooldowns;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseHandler;
import me.SuperRonanCraft.BetterRTP.references.file.FileOther;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.player.HelperPlayer;
import me.SuperRonanCraft.BetterRTP.references.player.playerdata.PlayerData;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.worlds.WorldPlayer;
@@ -18,6 +19,7 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class CooldownHandler {
@@ -43,7 +45,7 @@ public class CooldownHandler {
}
private void queueDownload() {
Bukkit.getScheduler().runTaskLaterAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runLaterAsync(() -> {
if (cooldownByWorld && !DatabaseHandler.getCooldowns().isLoaded()) {
queueDownload();
return;
@@ -57,7 +59,7 @@ public class CooldownHandler {
for (Player p : Bukkit.getOnlinePlayers())
loadPlayer(p);
loaded = true;
}, 10L);
}, 10L * 50L, TimeUnit.MILLISECONDS);
}
public void add(Player player, World world) {
@@ -132,7 +134,7 @@ public class CooldownHandler {
}
private void savePlayer(Player player, @Nullable World world, @Nullable CooldownData data, boolean remove) {
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
if (world != null && data != null && getDatabaseWorlds() != null) { //Per World enabled?
if (!remove)
getDatabaseWorlds().setCooldown(world, data);

View File

@@ -1,11 +1,13 @@
package me.SuperRonanCraft.BetterRTP.references.rtpinfo;
import com.tcoded.folialib.wrapper.WrappedTask;
import io.papermc.lib.PaperLib;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.player.commands.RTP_SETUP_TYPE;
import me.SuperRonanCraft.BetterRTP.player.rtp.RTP;
import me.SuperRonanCraft.BetterRTP.player.rtp.RTPPlayer;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseHandler;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.helpers.HelperRTP;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.worlds.RTPWorld;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.worlds.WorldCustom;
@@ -19,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class QueueGenerator {
@@ -27,23 +30,22 @@ public class QueueGenerator {
public static final int queueMax = 32, queueMin = 2; //Amount to ready up for each rtp world
private final int queueMaxAttempts = 50;
boolean generating;
private BukkitTask task;
private WrappedTask task;
public void unload() {
if (task != null)
Bukkit.getScheduler().cancelTask(task.getTaskId());
task.cancel();
}
public void load() {
unload();
loaded = false;
if (task != null)
Bukkit.getScheduler().cancelTask(task.getTaskId());
generate(null);
}
void generate(@Nullable RTPWorld rtpWorld) {
if (!QueueHandler.isEnabled()) return;
Bukkit.getScheduler().runTaskLaterAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runLaterAsync(() -> {
if (!DatabaseHandler.getQueue().isLoaded()) {
generate(rtpWorld);
return;
@@ -53,12 +55,12 @@ public class QueueGenerator {
//Queue after everything was loaded
BetterRTP.debug("Attempting to queue up some more safe locations...");
queueGenerator(new ReQueueData(rtpWorld, queueMax, queueMin, 0, "noone", 0));
}, 10L);
}, 10L * 50L, TimeUnit.MILLISECONDS);
}
private void queueGenerator(ReQueueData data) {
generating = true;
task = Bukkit.getScheduler().runTaskLaterAsynchronously(BetterRTP.getInstance(), () -> {
task = FoliaHelper.get().runLaterAsync(() -> {
//BetterRTP.debug("Generating a new position... attempt # " + data.attempts);
//Generate more locations
//Rare cases where a rtp world didn't have a location generated (Permission Groups?)
@@ -107,7 +109,7 @@ public class QueueGenerator {
}
generating = false;
BetterRTP.debug("Queueing paused, max queue limit reached!");
}, 20L /*delay before starting queue generator*/);
}, 20L * 50L /*delay before starting queue generator*/, TimeUnit.MILLISECONDS);
}
static class ReQueueData {
@@ -152,7 +154,7 @@ public class QueueGenerator {
private void addQueue(RTPWorld rtpWorld, String id, ReQueueData reQueueData) {
Location loc = RandomLocation.generateLocation(rtpWorld);
if (loc != null) {
Bukkit.getScheduler().runTask(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runNextTick(() -> {
//BetterRTP.debug("Queued up a new position, attempts " + reQueueData.attempts);
PaperLib.getChunkAtAsync(loc)
.thenAccept(v -> {
@@ -165,7 +167,7 @@ public class QueueGenerator {
rtpWorld.getBiomes());
//data.setLocation(safeLoc);
if (safeLoc != null) {
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
QueueData data = DatabaseHandler.getQueue().addQueue(safeLoc);
if (data != null) {
//queueList.add(data);

View File

@@ -4,6 +4,7 @@ import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.customEvents.RTP_TeleportPostEvent;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseHandler;
import me.SuperRonanCraft.BetterRTP.references.database.DatabaseQueue;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import me.SuperRonanCraft.BetterRTP.references.rtpinfo.worlds.RTPWorld;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -84,7 +85,7 @@ public class QueueHandler implements Listener { //Randomly queues up some safe l
public static void remove(Location loc) {
if (!isEnabled()) return;
Bukkit.getScheduler().runTaskAsynchronously(BetterRTP.getInstance(), () -> {
FoliaHelper.get().runAsync(() -> {
//Delete all queue data async
if (DatabaseHandler.getQueue().removeLocation(loc)) {
//BetterRTP.getInstance().getQueue().queueList.remove(data);

View File

@@ -1,5 +1,6 @@
package me.SuperRonanCraft.BetterRTP.references.web;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.ServicePriority;
@@ -127,12 +128,7 @@ public class Metrics {
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
submitData();
}
});
FoliaHelper.get().runNextTick(() -> submitData());
}
}, 1000*60*5, 1000*60*30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start

View File

@@ -1,6 +1,7 @@
package me.SuperRonanCraft.BetterRTP.references.web;
import me.SuperRonanCraft.BetterRTP.BetterRTP;
import me.SuperRonanCraft.BetterRTP.references.helpers.FoliaHelper;
import org.bukkit.Bukkit;
import java.io.BufferedReader;
@@ -13,7 +14,7 @@ public class Updater {
public static String updatedVersion = BetterRTP.getInstance().getDescription().getVersion();
public Updater(BetterRTP pl) {
Bukkit.getScheduler().runTaskAsynchronously(pl, () -> {
FoliaHelper.get().runAsync(() -> {
try {
URLConnection con = new URL(getUrl() + project()).openConnection();
updatedVersion = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();