Fix issue where old player objects were not cleaned up properly.

This is caused by an issue with the event order in Spigot (and Spigot derivatives), so the fix is rather hacky.
This commit is contained in:
Alexander Söderberg 2020-06-23 18:36:53 +02:00
parent f4724a3c87
commit 55cf34508a
No known key found for this signature in database
GPG Key ID: C0207FF7EA146678
5 changed files with 46 additions and 18 deletions

View File

@ -392,6 +392,19 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain<
PlotSquared.log( PlotSquared.log(
Captions.PREFIX.getTranslated() + "Using platform world manager: " + this.worldManager Captions.PREFIX.getTranslated() + "Using platform world manager: " + this.worldManager
.getName()); .getName());
// Clean up potential memory leak
Bukkit.getScheduler().runTaskTimer(this, () -> {
try {
for (final PlotPlayer<? extends Player> player : this.getPlayerManager().getPlayers()) {
if (player.getPlatformPlayer() == null || !player.getPlatformPlayer().isOnline()) {
this.getPlayerManager().removePlayer(player);
}
}
} catch (final Exception e) {
getLogger().warning("Failed to clean up players: " + e.getMessage());
}
}, 100L, 100L);
} }
private void unload() { private void unload() {
@ -982,7 +995,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain<
} }
@Override public void unregister(@NonNull final PlotPlayer player) { @Override public void unregister(@NonNull final PlotPlayer player) {
BukkitUtil.removePlayer(player.getName()); BukkitUtil.removePlayer(player.getUUID());
} }
@Override public void registerChunkProcessor() { @Override public void registerChunkProcessor() {

View File

@ -650,10 +650,10 @@ public class PlayerEvents extends PlotListener implements Listener {
PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid); PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid);
} }
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onConnect(PlayerJoinEvent event) { public void onConnect(PlayerJoinEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
BukkitUtil.removePlayer(player.getName()); BukkitUtil.removePlayer(player.getUniqueId());
final PlotPlayer<Player> pp = BukkitUtil.getPlayer(player); final PlotPlayer<Player> pp = BukkitUtil.getPlayer(player);
Location location = pp.getLocation(); Location location = pp.getLocation();

View File

@ -116,9 +116,11 @@ public class BukkitUtil extends WorldUtil {
private static Player lastPlayer = null; private static Player lastPlayer = null;
private static BukkitPlayer lastPlotPlayer = null; private static BukkitPlayer lastPlotPlayer = null;
public static void removePlayer(String player) { public static void removePlayer(UUID uuid) {
lastPlayer = null; lastPlayer = null;
lastPlotPlayer = null; lastPlotPlayer = null;
// Make sure that it's removed internally
PlotSquared.imp().getPlayerManager().removePlayer(uuid);
} }
public static PlotPlayer<Player> getPlayer(@NonNull final OfflinePlayer op) { public static PlotPlayer<Player> getPlayer(@NonNull final OfflinePlayer op) {

View File

@ -2917,7 +2917,7 @@ public class Plot {
*/ */
public void reEnter() { public void reEnter() {
TaskManager.runTaskLater(() -> { TaskManager.runTaskLater(() -> {
for (PlotPlayer pp : Plot.this.getPlayersInPlot()) { for (PlotPlayer<?> pp : Plot.this.getPlayersInPlot()) {
PlotListener.plotExit(pp, Plot.this); PlotListener.plotExit(pp, Plot.this);
PlotListener.plotEntry(pp, Plot.this); PlotListener.plotEntry(pp, Plot.this);
} }
@ -2925,18 +2925,19 @@ public class Plot {
} }
public void debug(@NotNull final String message) { public void debug(@NotNull final String message) {
try {
final Collection<PlotPlayer<?>> players = PlotPlayer.getDebugModePlayersInPlot(this); final Collection<PlotPlayer<?>> players = PlotPlayer.getDebugModePlayersInPlot(this);
if (players.isEmpty()) { if (players.isEmpty()) {
return; return;
} }
final String string = Captions.PLOT_DEBUG.getTranslated().replace("%plot%", this.toString()) final String string =
.replace("%message%", message); Captions.PLOT_DEBUG.getTranslated().replace("%plot%", this.toString()).replace("%message%", message);
for (final PlotPlayer<?> player : players) { for (final PlotPlayer<?> player : players) {
if (isOwner(player.getUUID()) || if (isOwner(player.getUUID()) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_DEBUG_OTHER)) {
Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_DEBUG_OTHER)) {
player.sendMessage(string); player.sendMessage(string);
} }
} }
} catch (final Exception ignored) {}
} }
/** /**

View File

@ -30,6 +30,7 @@ import com.plotsquared.core.player.PlotPlayer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -55,6 +56,17 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
} }
} }
/**
* Remove a player from the player map
*
* @param uuid Player to remove
*/
public void removePlayer(@NotNull final UUID uuid) {
synchronized (playerLock) {
this.playerMap.remove(uuid);
}
}
/** /**
* Get the player from its UUID if it is stored in the player map. * Get the player from its UUID if it is stored in the player map.
* *
@ -110,7 +122,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
} }
} }
@NotNull protected abstract P createPlayer(@NotNull final UUID uuid); @NotNull public abstract P createPlayer(@NotNull final UUID uuid);
/** /**
* Get an an offline player object from the player's UUID * Get an an offline player object from the player's UUID
@ -134,7 +146,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
* @return Unmodifiable collection of players * @return Unmodifiable collection of players
*/ */
public Collection<P> getPlayers() { public Collection<P> getPlayers() {
return Collections.unmodifiableCollection(this.playerMap.values()); return Collections.unmodifiableCollection(new ArrayList<>(this.playerMap.values()));
} }