Skip to content

Commit

Permalink
Improve getting respawn location for folia
Browse files Browse the repository at this point in the history
  • Loading branch information
Warriorrrr committed Jan 20, 2025
1 parent 1b3a8ad commit 08ffddd
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,16 @@ public void onPlayerRespawn(PlayerRespawnEvent event) {
Resident resident = TownyAPI.getInstance().getResident(player);

// Towny or the Resident might be prioritizing bed spawns over town spawns.
if (TownySettings.getBedUse() ||
(resident != null && resident.hasMode("bedspawn"))) {
Location bed = BukkitTools.getBedOrRespawnLocation(player);
if (bed != null)
respawn = bed;
if (TownySettings.getBedUse() || (resident != null && resident.hasMode("bedspawn"))) {
// Get the potential respawn location first to check the world
final Location potentialLocation = TownySettings.isTownRespawningInOtherWorlds() ? null : BukkitTools.getPotentialRespawnLocation(player);

if (potentialLocation == null || player.getWorld().equals(potentialLocation.getWorld())) {

Location respawnBlock = BukkitTools.findRespawnBlock(player);
if (respawnBlock != null)
respawn = respawnBlock;
}
}

// Town spawn could be null and no bed was available.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ private void cleanupBackups() {

long deleteAfter = TownySettings.getBackupLifeLength();
if (deleteAfter >= 0) {
File backupDirectory = new File(TownyUniverse.getInstance().getRootFolder() + File.separator + "backup");
if (!backupDirectory.exists())
return;

Towny.getPlugin().getLogger().info("Cleaning up old backups...");

if (FileMgmt.deleteOldBackups(new File(TownyUniverse.getInstance().getRootFolder() + File.separator + "backup"), deleteAfter))
if (FileMgmt.deleteOldBackups(backupDirectory, deleteAfter))
Towny.getPlugin().getLogger().info("Successfully cleaned backups.");
else
Towny.getPlugin().getLogger().info("Could not delete old backups.");
Expand Down
49 changes: 40 additions & 9 deletions Towny/src/main/java/com/palmergames/bukkit/util/BukkitTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.palmergames.bukkit.towny.hooks.PluginIntegrations;
import com.palmergames.bukkit.towny.utils.MinecraftVersion;

import com.palmergames.util.JavaUtil;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Location;
Expand All @@ -19,6 +20,7 @@
import org.bukkit.World;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
Expand All @@ -33,7 +35,6 @@
import org.jetbrains.annotations.Nullable;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
Expand All @@ -44,6 +45,8 @@
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.stream.Collectors;

/**
Expand All @@ -58,6 +61,7 @@ public class BukkitTools {
@SuppressWarnings("unused")
private static Towny plugin = null;
private static final MethodHandle GET_OFFLINE_PLAYER_CACHED;
private static final MethodHandle GET_POTENTIAL_RESPAWN_LOCATION;

public static void initialize(Towny plugin) {
BukkitTools.plugin = plugin;
Expand Down Expand Up @@ -267,9 +271,41 @@ public static List<String> getWorldNames() {
public static List<String> getWorldNames(boolean lowercased) {
return lowercased ? getWorlds().stream().map(world -> world.getName().toLowerCase(Locale.ROOT)).collect(Collectors.toList()) : getWorldNames();
}

public static Location findRespawnBlock(Player player) {
final Location potentialLocation = getPotentialRespawnLocation(player);

if (potentialLocation != null && !plugin.getScheduler().isRegionThread(potentialLocation)) {
// Getting the respawn location can load chunks, so we have to make sure we're on the region thread for the potential location

CompletableFuture<Location> future = new CompletableFuture<>();
plugin.getScheduler().run(potentialLocation, () -> {
try {
future.complete(getRespawnLocation(player));
} catch (Throwable throwable) {
plugin.getLogger().log(Level.SEVERE, "Exception occurred while getting respawn location", throwable);
future.completeExceptionally(throwable);
}
});

return future.join();
}

return getRespawnLocation(player);
}

@Nullable
public static Location getPotentialRespawnLocation(HumanEntity player) {
try {
return (Location) GET_POTENTIAL_RESPAWN_LOCATION.invokeExact(player);
} catch (Throwable throwable) {
plugin.getLogger().log(Level.SEVERE, "Exception occurred while getting potential respawn location", throwable); // TODO: remove
return null;
}
}

@SuppressWarnings("deprecation")
public static Location getBedOrRespawnLocation(Player player) {
public static Location getRespawnLocation(Player player) {
return MinecraftVersion.CURRENT_VERSION.isOlderThanOrEquals(MinecraftVersion.MINECRAFT_1_20_3)
? player.getBedSpawnLocation() : player.getRespawnLocation();
}
Expand Down Expand Up @@ -371,12 +407,7 @@ public static Collection<String> convertKeyedToString(@NotNull Collection<? exte
}

static {
MethodHandle temp = null;
try {
//noinspection JavaReflectionMemberAccess
temp = MethodHandles.publicLookup().unreflect(Server.class.getMethod("getOfflinePlayerIfCached", String.class));
} catch (ReflectiveOperationException ignored) {}

GET_OFFLINE_PLAYER_CACHED = temp;
GET_OFFLINE_PLAYER_CACHED = JavaUtil.getMethodHandle(Server.class, "getOfflinePlayerIfCached", String.class);
GET_POTENTIAL_RESPAWN_LOCATION = JavaUtil.getMethodHandle(HumanEntity.class, "getPotentialBedLocation");
}
}

0 comments on commit 08ffddd

Please sign in to comment.