Make removal of unused playerdata more predictable and independent of

JOIN/LEAVE events.
This commit is contained in:
Evenprime 2011-10-23 16:05:18 +02:00
parent a6ae2d1e90
commit 15e5367175
6 changed files with 39 additions and 112 deletions

View File

@ -3,7 +3,7 @@ name: NoCheat
author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheat
version: 2.13a
version: 2.13b
commands:
nocheat:

View File

@ -29,7 +29,6 @@ import cc.co.evenprime.bukkit.nocheat.events.BlockBreakEventManager;
import cc.co.evenprime.bukkit.nocheat.events.EntityDamageEventManager;
import cc.co.evenprime.bukkit.nocheat.events.EventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerChatEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerQuitEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerMoveEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerTeleportEventManager;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
@ -101,7 +100,6 @@ public class NoCheat extends JavaPlugin {
eventManagers.add(new PlayerChatEventManager(this));
eventManagers.add(new BlockBreakEventManager(this));
eventManagers.add(new BlockPlaceEventManager(this));
eventManagers.add(new PlayerQuitEventManager(this));
eventManagers.add(new EntityDamageEventManager(this));
// Then set up a task to monitor server lag
@ -137,26 +135,14 @@ public class NoCheat extends JavaPlugin {
data.clearCriticalData(playerName);
}
public void playerLeft(String playerName) {
// Get rid of the critical data that's stored for player immediately
clearCriticalData(playerName);
data.queueForRemoval(playerName);
}
public void playerJoined(String playerName) {
data.unqueueForRemoval(playerName);
clearCriticalData(playerName);
}
public Performance getPerformance(Type type) {
return performance.get(type);
}
public void cleanDataMap() {
if(data != null)
data.cleanDataMap();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return CommandHandler.handleCommand(this, sender, command, label, args);
@ -197,6 +183,16 @@ public class NoCheat extends JavaPlugin {
public void reloadConfig() {
conf.cleanup();
this.conf = new ConfigurationManager(this.getDataFolder().getPath());
this.data.clearCriticalData();
data.cleanDataMap();
data.clearCriticalData();
}
/**
* Call this periodically to walk over the stored data map and remove old/unused entries
*
*/
public void cleanDataMap() {
data.cleanDataMap();
}
}

View File

@ -9,9 +9,9 @@ public class BaseData extends Data {
public final MovingData moving;
public final FightData fight;
private final Data[] data; // for convenience
private final Data[] data; // for convenience
private long removalTime;
public long lastUsedTime;
public BaseData() {
this.blockbreak = new BlockBreakData();
@ -21,8 +21,6 @@ public class BaseData extends Data {
this.moving = new MovingData();
this.fight = new FightData();
this.removalTime = 0;
data = new Data[] {this.blockbreak, this.blockplace, this.chat,
this.log, this.moving, this.fight};
}
@ -32,17 +30,8 @@ public class BaseData extends Data {
d.clearCriticalData();
}
}
public void markForRemoval(boolean removal) {
if(removal) {
// 1 minute in the future
this.removalTime = System.currentTimeMillis() + 60000;
} else {
this.removalTime = 0;
}
}
public boolean shouldBeRemoved() {
return removalTime != 0 && removalTime < System.currentTimeMillis();
public boolean shouldBeRemoved(long currentTimeInMilliseconds) {
return lastUsedTime + 60000L < currentTimeInMilliseconds;
}
}

View File

@ -40,6 +40,8 @@ public class DataManager {
this.map.put(playerName, data);
}
data.lastUsedTime = System.currentTimeMillis();
return data;
}
@ -54,47 +56,28 @@ public class DataManager {
}
/**
* put a players data on the queue for later deletion (unless it comes back
* before)
*
*/
public void queueForRemoval(String playerName) {
BaseData data = this.map.get(playerName);
if(data != null) {
data.markForRemoval(true);
}
}
public void unqueueForRemoval(String playerName) {
BaseData data = this.map.get(playerName);
if(data != null) {
data.markForRemoval(false);
}
}
/**
* check if queued for removal data is ready to get removed
* check if some data hasn't been used for a while and remove it
*
*/
public void cleanDataMap() {
try {
for(Entry<String, BaseData> p : this.map.entrySet()) {
if(p.getValue().shouldBeRemoved()) {
removals.add(p.getKey());
synchronized(removals) {
long time = System.currentTimeMillis();
try {
for(Entry<String, BaseData> p : this.map.entrySet()) {
if(p.getValue().shouldBeRemoved(time)) {
removals.add(p.getKey());
}
}
}
for(String p : removals) {
this.map.remove(p);
}
for(String p : removals) {
this.map.remove(p);
}
removals.clear();
} catch(Exception e) {
// Ignore problems, as they really don't matter much
removals.clear();
} catch(Exception e) {
e.printStackTrace();
}
}
}
public void clearCriticalData(String playerName) {

View File

@ -9,6 +9,7 @@ public class LagMeasureTask implements Runnable {
private long lastIngamesecondDuration = 2000L;
private boolean skipCheck = true;
private int lagMeasureTaskId = -1;
private final NoCheat plugin;
public LagMeasureTask(NoCheat plugin) {
@ -38,7 +39,9 @@ public class LagMeasureTask implements Runnable {
ingameseconds++;
// Check if some data is outdated now and let it be removed
plugin.cleanDataMap();
if(ingameseconds % 62 == 0) {
plugin.cleanDataMap();
}
}

View File

@ -1,44 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.events;
import java.util.Collections;
import java.util.List;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
public class PlayerQuitEventManager extends PlayerListener implements EventManager {
private final NoCheat plugin;
public PlayerQuitEventManager(NoCheat plugin) {
this.plugin = plugin;
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvent(Event.Type.PLAYER_QUIT, this, Priority.Monitor, plugin);
pm.registerEvent(Event.Type.PLAYER_JOIN, this, Priority.Monitor, plugin);
}
@Override
public void onPlayerQuit(PlayerQuitEvent event) {
// But only after a certain time, get rid of the rest of the data
plugin.playerLeft(event.getPlayer().getName());
}
@Override
public void onPlayerJoin(PlayerJoinEvent event) {
// A player came back early, so make sure that his data gets recycled
plugin.playerJoined(event.getPlayer().getName());
}
public List<String> getActiveChecks(ConfigurationCache cc) {
return Collections.emptyList();
}
}