Skip to content

Commit

Permalink
Get bed spawn locations async in SpawnUtil (#5728)
Browse files Browse the repository at this point in the history
* Get bed spawn locations async in SpawnUtil

* Don't call getBedSpawnLocation sync twice.

* Remove last use of sync get bed spawn in SpawnUtil
  • Loading branch information
Warriorrrr authored Feb 21, 2022
1 parent bb65c05 commit 041cbd6
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
172 changes: 85 additions & 87 deletions src/com/palmergames/bukkit/towny/utils/SpawnUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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);
});
}

/**
Expand All @@ -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);
});
}

/**
Expand Down Expand Up @@ -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.
Expand All @@ -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<Location> 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());
};
}

/**
Expand Down Expand Up @@ -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<Location> 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);
}

/**
Expand All @@ -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<Location> loc, boolean ignoreWarmup) {
loc.thenAccept(location -> initiatePluginTeleport(resident, location, ignoreWarmup));
}
}

0 comments on commit 041cbd6

Please sign in to comment.