Plug up memory leaks in IdleManager (#224)

Somehow, IdleManager was keeping Player references loaded
despite having removed them on PlayerQuitEvent.

This may be because of the runnable scheduled for 5 ticks after a teleport
which would insert players after they quit.

In any case, this was keeping entire worlds loaded in UHC. Pretty bad.

Moral of the story? Use UUIDs!
This commit is contained in:
Sam Sun 2016-09-29 23:29:53 -04:00 committed by Shaun Bennett
parent 0caa84f703
commit 81070eac62

View File

@ -3,6 +3,8 @@ package nautilus.game.arcade.managers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
@ -26,32 +28,54 @@ import nautilus.game.arcade.game.Game.GameState;
public class IdleManager implements Listener
{
private final ArcadeManager _arcadeManager;
private final Map<Player, Float> _yaw = new HashMap<>();
private final Map<Player, Long> _idle = new HashMap<>();
private final Map<Player, Integer> _beep = new HashMap<>();
private final HashSet<Player> _teleported = new HashSet();
private final Map<UUID, Float> _yaw = new HashMap<>();
private final Map<UUID, Long> _idle = new HashMap<>();
private final Map<UUID, Integer> _beep = new HashMap<>();
private final Set<UUID> _teleported = new HashSet<>();
public IdleManager(ArcadeManager manager)
{
_arcadeManager = manager;
Bukkit.getPluginManager().registerEvents(this, getArcadeManager().getPlugin());
UtilServer.RegisterEvents(this);
}
@EventHandler
public void ChatIdle(final AsyncPlayerChatEvent event)
public void onPlayerQuit(PlayerQuitEvent event)
{
if (!getArcadeManager().IsPlayerKickIdle())
return;
Bukkit.getServer().getScheduler().runTaskLater(getArcadeManager().getPlugin(), new Runnable()
_yaw.remove(event.getPlayer().getUniqueId());
_idle.remove(event.getPlayer().getUniqueId());
_beep.remove(event.getPlayer().getUniqueId());
_teleported.remove(event.getPlayer().getUniqueId());
}
@EventHandler
public void playerTeleport(PlayerTeleportEvent event)
{
_teleported.add(event.getPlayer().getUniqueId());
_arcadeManager.runSyncLater(() ->
{
@Override
public void run()
if (event.getPlayer().isOnline())
{
_idle.put(event.getPlayer(), System.currentTimeMillis());
_yaw.put(event.getPlayer().getUniqueId(), event.getPlayer().getLocation().getYaw());
_teleported.remove(event.getPlayer().getUniqueId());
}
}, 1);
}, 5);
}
@EventHandler
public void idleChat(final AsyncPlayerChatEvent event)
{
if (!_arcadeManager.IsPlayerKickIdle())
return;
_arcadeManager.runSyncLater(() ->
{
if (event.getPlayer().isOnline())
{
_idle.put(event.getPlayer().getUniqueId(), System.currentTimeMillis());
}
}, 1L);
}
@EventHandler
@ -59,100 +83,71 @@ public class IdleManager implements Listener
{
if (event.getType() != UpdateType.FAST)
return;
if (!getArcadeManager().IsPlayerKickIdle())
return;
if (getArcadeManager().GetGame() == null)
if (!_arcadeManager.IsPlayerKickIdle())
return;
for (Player player : UtilServer.getPlayers())
if (_arcadeManager.GetGame() == null)
return;
for (Player player : UtilServer.getPlayersCollection())
{
if (_teleported.contains(player))
if (_teleported.contains(player.getUniqueId()))
continue;
if (!_yaw.containsKey(player) || !_idle.containsKey(player))
if (!_yaw.containsKey(player.getUniqueId()) || !_idle.containsKey(player.getUniqueId()))
{
_yaw.put(player, player.getLocation().getYaw());
_idle.put(player, System.currentTimeMillis());
_yaw.put(player.getUniqueId(), player.getLocation().getYaw());
_idle.put(player.getUniqueId(), System.currentTimeMillis());
}
if (_yaw.get(player) == player.getLocation().getYaw())
{
if (UtilTime.elapsed(_idle.get(player), getArcadeManager().GetGame().IsLive() ? 240000 : 120000))
if (_yaw.get(player.getUniqueId()) == player.getLocation().getYaw())
{
if (UtilTime.elapsed(_idle.get(player.getUniqueId()), _arcadeManager.GetGame().IsLive() ? 240000 : 120000))
{
if (getArcadeManager().GetGame().GetState() != GameState.Recruit && !getArcadeManager().GetGame().IsAlive(player))
if (_arcadeManager.GetGame().GetState() != GameState.Recruit && !_arcadeManager.GetGame().IsAlive(player))
continue;
if (getArcadeManager().GetClients().Get(player).GetRank().has(Rank.MODERATOR))
if (_arcadeManager.GetClients().Get(player).GetRank().has(Rank.MODERATOR))
continue;
//Start Beeps
if (!_beep.containsKey(player))
if (!_beep.containsKey(player.getUniqueId()))
{
_beep.put(player, 20);
_beep.put(player.getUniqueId(), 20);
}
//Countdown
else
{
int count = _beep.get(player);
int count = _beep.get(player.getUniqueId());
if (count == 0)
{
player.playSound(player.getLocation(), Sound.ENDERDRAGON_GROWL, 10f, 1f);
getArcadeManager().GetPortal().sendPlayerToServer(player, "Lobby");
_arcadeManager.GetPortal().sendPlayerToServer(player, "Lobby");
}
else
{
float scale = (float) (0.8 + (((double)count/20d)*1.2));
{
float scale = (float) (0.8 + (((double) count / 20d) * 1.2));
player.playSound(player.getLocation(), Sound.NOTE_PLING, scale, scale);
if (count%2 == 0)
if (count % 2 == 0)
{
UtilPlayer.message(player, C.cGold + C.Bold + "You will be AFK removed in " + (count/2) + " seconds...");
UtilPlayer.message(player, C.cGold + C.Bold + "You will be AFK removed in " + (count / 2) + " seconds...");
}
count--;
_beep.put(player, count);
_beep.put(player.getUniqueId(), count);
}
}
}
}
continue;
}
_yaw.put(player, player.getLocation().getYaw());
_idle.put(player, System.currentTimeMillis());
_beep.remove(player);
else
{
_yaw.put(player.getUniqueId(), player.getLocation().getYaw());
_idle.put(player.getUniqueId(), System.currentTimeMillis());
_beep.remove(player.getUniqueId());
}
}
}
@EventHandler
public void playerTeleport(PlayerTeleportEvent event)
{
_teleported.add(event.getPlayer());
_arcadeManager.runSyncLater(new Runnable()
{
@Override
public void run()
{
_yaw.put(event.getPlayer(), event.getPlayer().getLocation().getYaw());
_teleported.remove(event.getPlayer());
}
}, 5);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
_yaw.remove(event.getPlayer());
_idle.remove(event.getPlayer());
_beep.remove(event.getPlayer());
_teleported.remove(event.getPlayer());
}
public ArcadeManager getArcadeManager()
{
return _arcadeManager;
}
}