diff --git a/src/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java b/src/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java index 4f9c65b1ba..c0ccd3a3a4 100644 --- a/src/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java +++ b/src/com/palmergames/bukkit/towny/listeners/TownyPlayerListener.java @@ -77,7 +77,6 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.scheduler.BukkitRunnable; import java.util.Arrays; import java.util.HashMap; @@ -898,13 +897,11 @@ public void onOutlawEnterTown(PlayerEnterTownEvent event) { if (TownySettings.getOutlawTeleportWarmup() > 0) { TownyMessaging.sendMsg(outlaw, Translatable.of("msg_outlaw_kick_cooldown", town, TimeMgmt.formatCountdownTime(TownySettings.getOutlawTeleportWarmup()))); } - new BukkitRunnable() { - @Override - public void run() { - if (TownyAPI.getInstance().getTown(outlaw.getPlayer().getLocation()) != null && TownyAPI.getInstance().getTown(outlaw.getPlayer().getLocation()) == town && town.hasOutlaw(outlaw.getPlayer().getName())) - SpawnUtil.outlawTeleport(town, outlaw); - } - }.runTaskLater(plugin, TownySettings.getOutlawTeleportWarmup() * 20); + + Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> { + if (TownyAPI.getInstance().getTown(outlaw.getPlayer().getLocation()) != null && TownyAPI.getInstance().getTown(outlaw.getPlayer().getLocation()) == town && town.hasOutlaw(outlaw.getPlayer().getName())) + SpawnUtil.outlawTeleport(town, outlaw); + }, TownySettings.getOutlawTeleportWarmup() * 20L); } } } diff --git a/src/com/palmergames/bukkit/towny/utils/SpawnUtil.java b/src/com/palmergames/bukkit/towny/utils/SpawnUtil.java index eb186599fe..2d34ef2553 100644 --- a/src/com/palmergames/bukkit/towny/utils/SpawnUtil.java +++ b/src/com/palmergames/bukkit/towny/utils/SpawnUtil.java @@ -2,6 +2,8 @@ import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; + import com.palmergames.bukkit.towny.event.NationSpawnEvent; import com.palmergames.bukkit.towny.event.SpawnEvent; import com.palmergames.bukkit.towny.event.TownSpawnEvent; @@ -65,44 +67,27 @@ public static void sendToTownySpawn(Player player, String[] split, TownyObject t Resident resident = getResident(player); // Set up town and nation variables. - Town town = null; - Nation nation = null; - switch (spawnType) { - case RESIDENT: - town = resident.getTownOrNull(); - break; - case TOWN: - town = (Town) townyObject; - break; - case NATION: - nation = (Nation) townyObject; - break; - default: - } + final Town town = switch (spawnType) { + case RESIDENT -> resident.getTownOrNull(); + case TOWN -> (Town) townyObject; + default -> null; + }; + + final Nation nation = spawnType == SpawnType.NATION ? (Nation) townyObject : null; // Is this an admin spawning? boolean isTownyAdmin = isTownyAdmin(player); - - // Get the location we're spawning to. - final Location spawnLoc = getSpawnLoc(player, resident, town, nation, spawnType, outpost, split); // Set up either the townSpawnLevel or nationSpawnLevel variable. // This determines whether a spawn is considered town, nation, public, allied, admin via TownSpawnLevel and NationSpawnLevel objects. // Accounts for costs, permission, config settings and messages. - TownSpawnLevel townSpawnLevel = null; - NationSpawnLevel nationSpawnLevel = null; - switch (spawnType) { - case RESIDENT: - townSpawnLevel = isTownyAdmin ? TownSpawnLevel.ADMIN : TownSpawnLevel.TOWN_RESIDENT; - break; - case TOWN: - townSpawnLevel = isTownyAdmin ? TownSpawnLevel.ADMIN : getTownSpawnLevel(player, resident, town, outpost, split.length == 0); - break; - case NATION: - nationSpawnLevel = isTownyAdmin ? NationSpawnLevel.ADMIN : getNationSpawnLevel(player, resident, nation, split.length == 0); - break; - default: - } + final TownSpawnLevel townSpawnLevel = switch (spawnType) { + case RESIDENT -> isTownyAdmin ? TownSpawnLevel.ADMIN : TownSpawnLevel.TOWN_RESIDENT; + case TOWN -> isTownyAdmin ? TownSpawnLevel.ADMIN : getTownSpawnLevel(player, resident, town, outpost, split.length == 0); + default -> null; + }; + + final NationSpawnLevel nationSpawnLevel = spawnType == SpawnType.NATION ? isTownyAdmin ? NationSpawnLevel.ADMIN : getNationSpawnLevel(player, resident, nation, split.length == 0) : null; // Prevent spawn travel while in the config's disallowed zones. // Throws a TownyException if the player is disallowed. @@ -115,20 +100,26 @@ public static void sendToTownySpawn(Player player, String[] split, TownyObject t // Don't allow if they cannot pay. if (travelCost > 0 && !resident.getAccount().canPayFromHoldings(travelCost)) throw new TownyException(notAffordMSG); - - // Fire a cancellable event right before a player would actually pay. - // Throws a TownyException if the event is cancelled. - sendSpawnEvent(player, spawnType, spawnLoc); - - // There is a cost to spawn, prompt with confirmation unless ignoreWarn is true. - if (travelCost > 0) { - // Get paymentMsg for the money.csv and the Account being paid. - final String paymentMsg = getPaymentMsg(townSpawnLevel, nationSpawnLevel, spawnType); - final Account payee = TownySettings.isTownSpawnPaidToTown() ? getPayee(town, nation, spawnType) : EconomyAccount.SERVER_ACCOUNT; - initiateCostedSpawn(player, resident, spawnLoc, travelCost, payee, paymentMsg, ignoreWarn); - // No Cost so skip confirmation system. - } else - initiateSpawn(player, spawnLoc); + + getSpawnLoc(player, town, nation, spawnType, outpost, split).thenAccept(spawnLoc -> { + // Fire a cancellable event right before a player would actually pay. + // Throws a TownyException if the event is cancelled. + try { + sendSpawnEvent(player, spawnType, spawnLoc); + } catch (TownyException e) { + TownyMessaging.sendErrorMsg(player, e.getMessage(player)); + } + + // There is a cost to spawn, prompt with confirmation unless ignoreWarn is true. + if (travelCost > 0) { + // Get paymentMsg for the money.csv and the Account being paid. + final String paymentMsg = getPaymentMsg(townSpawnLevel, nationSpawnLevel, spawnType); + final Account payee = TownySettings.isTownSpawnPaidToTown() ? getPayee(town, nation, spawnType) : EconomyAccount.SERVER_ACCOUNT; + initiateCostedSpawn(player, resident, spawnLoc, travelCost, payee, paymentMsg, ignoreWarn); + // No Cost so skip confirmation system. + } else + initiateSpawn(player, spawnLoc); + }); } /** @@ -138,19 +129,25 @@ public static void sendToTownySpawn(Player player, String[] split, TownyObject t * @param outlaw Resident which is outlawed and being moved. */ public static void outlawTeleport(Town town, Resident outlaw) { - Location spawnLocation = town.getWorld().getSpawnLocation(); Player outlawedPlayer = outlaw.getPlayer(); - if (!TownySettings.getOutlawTeleportWorld().equals("")) { - spawnLocation = Objects.requireNonNull(Bukkit.getWorld(TownySettings.getOutlawTeleportWorld())).getSpawnLocation(); - } + if (outlawedPlayer == null) + return; + // sets tp location to their bedspawn only if it isn't in the town they're being teleported from. - Location bed = outlawedPlayer.getBedSpawnLocation(); - if (bed != null && TownyAPI.getInstance().getTown(bed) != town) - spawnLocation = bed; - if (outlaw.hasTown() && TownyAPI.getInstance().getTownSpawnLocation(outlawedPlayer) != null) - spawnLocation = TownyAPI.getInstance().getTownSpawnLocation(outlawedPlayer); - TownyMessaging.sendMsg(outlaw, Translatable.of("msg_outlaw_kicked", town)); - initiatePluginTeleport(outlaw, spawnLocation, true); + PaperLib.getBedSpawnLocationAsync(outlawedPlayer, true).thenAccept(bed -> { + Location spawnLocation = town.getWorld().getSpawnLocation(); + if (!TownySettings.getOutlawTeleportWorld().equals("")) + spawnLocation = Objects.requireNonNull(Bukkit.getWorld(TownySettings.getOutlawTeleportWorld())).getSpawnLocation(); + + if (bed != null && TownyAPI.getInstance().getTown(bed) != town) + spawnLocation = bed; + + if (outlaw.hasTown() && TownyAPI.getInstance().getTownSpawnLocation(outlawedPlayer) != null) + spawnLocation = TownyAPI.getInstance().getTownSpawnLocation(outlawedPlayer); + + TownyMessaging.sendMsg(outlaw, Translatable.of("msg_outlaw_kicked", town)); + initiatePluginTeleport(outlaw, spawnLocation, true); + }); } /** @@ -327,7 +324,6 @@ private static NationSpawnLevel getNationSpawnLevel(Player player, Resident resi * Get the destination location of this Spawn action. * * @param player Player spawning. - * @param resident Resident of the player spawning. * @param town Town the player could be spawning to, or null. * @param nation Nation the player could be spawning to, or null. * @param spawnType SpawnType of this Spawn action. @@ -337,29 +333,30 @@ private static NationSpawnLevel getNationSpawnLevel(Player player, Resident resi * @throws TownyException thrown when the eventual spawn location is invalid or * the player is outlawed at that location. */ - private static Location getSpawnLoc(Player player, Resident resident, Town town, Nation nation, SpawnType spawnType, boolean outpost, String[] split) throws TownyException { - Location spawnLoc = null; - switch (spawnType) { - case RESIDENT: - if (TownySettings.getBedUse() && player.getBedSpawnLocation() != null) - spawnLoc = player.getBedSpawnLocation(); - else if (town != null && town.hasSpawn()) - spawnLoc = town.getSpawnOrNull(); - else - spawnLoc = plugin.getCache(player).getLastLocation().getWorld().getSpawnLocation(); - break; - case TOWN: - if (outpost) - spawnLoc = getOutpostSpawnLocation(town, split); - else - spawnLoc = town.getSpawn(); - break; - case NATION: - spawnLoc = nation.getSpawn(); - break; - default: - } - return spawnLoc; + private static CompletableFuture getSpawnLoc(Player player, Town town, Nation nation, SpawnType spawnType, boolean outpost, String[] split) throws TownyException { + return switch (spawnType) { + case RESIDENT: + if (TownySettings.getBedUse()) { + yield PaperLib.getBedSpawnLocationAsync(player, true).thenApply(bedLoc -> { + if (bedLoc != null) + return bedLoc; + else if (town != null && town.hasSpawn()) + return town.getSpawnOrNull(); + else + return plugin.getCache(player).getLastLocation().getWorld().getSpawnLocation(); + }); + } else if (town != null && town.hasSpawn()) + yield CompletableFuture.completedFuture(town.getSpawnOrNull()); + else + yield CompletableFuture.completedFuture(plugin.getCache(player).getLastLocation().getWorld().getSpawnLocation()); + case TOWN: + if (outpost) + yield CompletableFuture.completedFuture(getOutpostSpawnLocation(town, split)); + else + yield CompletableFuture.completedFuture(town.getSpawn()); + case NATION: + yield CompletableFuture.completedFuture(nation.getSpawn()); + }; } /** @@ -615,18 +612,15 @@ private static void payAndThenSpawn(Player player, Resident resident, Location s * @param resident Resident needing a location to spawn to. * @return bed spawn OR town spawn OR last world spawn */ - private static Location getIdealLocation(Resident resident) { + private static CompletableFuture getIdealLocation(Resident resident) { Town town = resident.getTownOrNull(); Location loc = resident.getPlayer().getWorld().getSpawnLocation(); if (town != null && town.hasSpawn()) loc = town.getSpawnOrNull(); - Location bed = resident.getPlayer().getBedSpawnLocation(); - if (bed != null) - loc = bed; - - return loc; + Location finalLoc = loc; + return PaperLib.getBedSpawnLocationAsync(resident.getPlayer(), true).thenApply(bed -> bed == null ? finalLoc : bed); } /** @@ -639,6 +633,10 @@ private static Location getIdealLocation(Resident resident) { */ private static void initiatePluginTeleport(Resident resident, Location loc, boolean ignoreWarmup) { Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> PaperLib.teleportAsync(resident.getPlayer(), loc, TeleportCause.PLUGIN), - ignoreWarmup ? 0 : TownySettings.getTeleportWarmupTime() * 20); + ignoreWarmup ? 0 : TownySettings.getTeleportWarmupTime() * 20L); + } + + private static void initiatePluginTeleport(Resident resident, CompletableFuture loc, boolean ignoreWarmup) { + loc.thenAccept(location -> initiatePluginTeleport(resident, location, ignoreWarmup)); } }