From 519485f1550bfa5638237d3b514f3e72c2cb98dd Mon Sep 17 00:00:00 2001 From: Glitchfinder Date: Mon, 18 Feb 2013 16:13:33 -0800 Subject: [PATCH] Converting entity tracking to use Bukkit metadata. Should greatly reduce lag on chunk loading and unloading. --- .../nossr50/listeners/EntityListener.java | 13 +- .../nossr50/listeners/WorldListener.java | 19 -- src/main/java/com/gmail/nossr50/mcMMO.java | 9 +- .../nossr50/runnables/MobStoreCleaner.java | 38 ---- .../taming/CallOfTheWildEventHandler.java | 2 +- .../nossr50/skills/taming/TamingManager.java | 5 +- .../nossr50/skills/utilities/CombatTools.java | 4 +- .../blockmeta/chunkmeta/ChunkManager.java | 8 - .../util/blockmeta/chunkmeta/ChunkStore.java | 11 - .../blockmeta/chunkmeta/HashChunkManager.java | 202 ------------------ .../blockmeta/chunkmeta/NullChunkManager.java | 15 -- .../chunkmeta/PrimitiveChunkStore.java | 90 +------- 12 files changed, 22 insertions(+), 394 deletions(-) delete mode 100755 src/main/java/com/gmail/nossr50/runnables/MobStoreCleaner.java diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 34a359237..fb8910827 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -65,13 +65,12 @@ public class EntityListener implements Listener { if (entity instanceof FallingBlock) { Block block = event.getBlock(); - if (mcMMO.placeStore.isTrue(block) && !mcMMO.placeStore.isSpawnedMob(entity)) { + if (mcMMO.placeStore.isTrue(block) && !entity.hasMetadata(mcMMO.entityMetadataKey)) { mcMMO.placeStore.setFalse(block); - mcMMO.placeStore.addSpawnedMob(entity); + entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.entityMetadata); } - else if (mcMMO.placeStore.isSpawnedMob(entity)) { + else if (entity.hasMetadata(mcMMO.entityMetadataKey)) { mcMMO.placeStore.setTrue(block); - mcMMO.placeStore.removeSpawnedMob(entity); } } } @@ -216,7 +215,6 @@ public class EntityListener implements Listener { entity.setFireTicks(0); BleedTimer.remove(entity); Archery.arrowRetrievalCheck(entity); - mcMMO.placeStore.removeSpawnedMob(entity); } /** @@ -229,11 +227,14 @@ public class EntityListener implements Listener { if (Misc.isSpawnerXPEnabled) { return; } + else if (event.getEntity() == null) { + return; + } SpawnReason reason = event.getSpawnReason(); if (reason == SpawnReason.SPAWNER || reason == SpawnReason.SPAWNER_EGG) { - mcMMO.placeStore.addSpawnedMob(event.getEntity()); + event.getEntity().setMetadata(mcMMO.entityMetadataKey, mcMMO.entityMetadata); } } diff --git a/src/main/java/com/gmail/nossr50/listeners/WorldListener.java b/src/main/java/com/gmail/nossr50/listeners/WorldListener.java index 508ff7b5f..c65d8bf45 100644 --- a/src/main/java/com/gmail/nossr50/listeners/WorldListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/WorldListener.java @@ -13,7 +13,6 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.StructureGrowEvent; import org.bukkit.event.world.WorldInitEvent; @@ -87,22 +86,4 @@ public class WorldListener implements Listener { mcMMO.placeStore.chunkUnloaded(chunk.getX(), chunk.getZ(), event.getWorld()); } - - /** - * Monitor ChunkLoad events. - * - * @param event The event to watch - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onChunkLoad(ChunkLoadEvent event) { - Chunk chunk = event.getChunk(); - Entity[] entities = chunk.getEntities(); - - for (Entity entity : entities) { - if (entity instanceof LivingEntity || entity instanceof FallingBlock) { - mcMMO.placeStore.loadChunk(chunk.getX(), chunk.getZ(), event.getWorld(), entities); - return; - } - } - } } diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index cba26f4c3..24b5e1e9d 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -11,6 +11,7 @@ import net.shatteredlands.shatt.backup.ZipLibrary; import org.bukkit.OfflinePlayer; import org.bukkit.block.Block; import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; @@ -40,7 +41,6 @@ import com.gmail.nossr50.mods.config.CustomToolsConfig; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.party.runnables.PartiesLoader; import com.gmail.nossr50.party.runnables.PartyAutoKick; -import com.gmail.nossr50.runnables.MobStoreCleaner; import com.gmail.nossr50.runnables.SaveTimer; import com.gmail.nossr50.skills.repair.RepairManager; import com.gmail.nossr50.skills.repair.RepairManagerFactory; @@ -86,12 +86,17 @@ public class mcMMO extends JavaPlugin { // XP Event Check private boolean xpEventEnabled = false; + // Entity Metadata Values + public static FixedMetadataValue entityMetadata; + public final static String entityMetadataKey = "mcMMO: Spawned Entity"; + /** * Things to be run when the plugin is enabled. */ @Override public void onEnable() { p = this; + entityMetadata = new FixedMetadataValue(mcMMO.p, true); setupFilePaths(); setupSpout(); loadConfigFiles(); @@ -125,8 +130,6 @@ public class mcMMO extends JavaPlugin { placeStore = ChunkManagerFactory.getChunkManager(); // Get our ChunkletManager - new MobStoreCleaner(); // Automatically starts and stores itself - try { updateAvailable = Config.getInstance().getUpdateCheckEnabled() && UpdateCheck.updateAvailable(); } catch (Exception e) { diff --git a/src/main/java/com/gmail/nossr50/runnables/MobStoreCleaner.java b/src/main/java/com/gmail/nossr50/runnables/MobStoreCleaner.java deleted file mode 100755 index 4261f1d5d..000000000 --- a/src/main/java/com/gmail/nossr50/runnables/MobStoreCleaner.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gmail.nossr50.runnables; - -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitScheduler; - -import com.gmail.nossr50.mcMMO; - -public class MobStoreCleaner implements Runnable { - private int taskID; - - public MobStoreCleaner() { - taskID = -1; - start(); - } - - public void start() { - if (taskID >= 0) { - return; - } - - BukkitScheduler scheduler = Bukkit.getServer().getScheduler(); - taskID = scheduler.scheduleSyncRepeatingTask(mcMMO.p, this, 12000, 12000); - } - - public void stop() { - if (taskID < 0) { - return; - } - - Bukkit.getServer().getScheduler().cancelTask(taskID); - taskID = -1; - } - - @Override - public void run() { - mcMMO.placeStore.cleanMobLists(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gmail/nossr50/skills/taming/CallOfTheWildEventHandler.java b/src/main/java/com/gmail/nossr50/skills/taming/CallOfTheWildEventHandler.java index c6de8e203..a253b1d24 100644 --- a/src/main/java/com/gmail/nossr50/skills/taming/CallOfTheWildEventHandler.java +++ b/src/main/java/com/gmail/nossr50/skills/taming/CallOfTheWildEventHandler.java @@ -67,7 +67,7 @@ public class CallOfTheWildEventHandler { return; LivingEntity entity = (LivingEntity) player.getWorld().spawnEntity(player.getLocation(), type); - mcMMO.placeStore.addSpawnedPet(entity); + entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.entityMetadata); ((Tameable) entity).setOwner(player); diff --git a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java index 3bd2651a7..6a4a94a69 100644 --- a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java @@ -27,7 +27,10 @@ public class TamingManager extends SkillManager { * @param event The event to award XP for */ public void awardTamingXP(EntityTameEvent event) { - if (mcMMO.placeStore.isSpawnedMob(event.getEntity())) { + if (event.getEntity() == null) { + return; + } + else if (event.getEntity().hasMetadata(mcMMO.entityMetadataKey)) { return; } diff --git a/src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java b/src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java index c99f17cde..97d172e74 100644 --- a/src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java +++ b/src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java @@ -456,8 +456,8 @@ public final class CombatTools { baseXP = 20 * configInstance.getPlayerVersusPlayerXP(); } } - else if (!mcMMO.placeStore.isSpawnedMob(target)) { - if (target instanceof Animals && !mcMMO.placeStore.isSpawnedPet(target)) { + else if (!target.hasMetadata(mcMMO.entityMetadataKey)) { + if (target instanceof Animals) { if (ModChecks.isCustomEntity(target)) { baseXP = ModChecks.getCustomEntity(target).getXpMultiplier(); } diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkManager.java index 9fee57617..da7c09840 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkManager.java @@ -166,12 +166,4 @@ public interface ChunkManager { * Delete any ChunkletStores that are empty */ public void cleanUp(); - - public boolean isSpawnedMob(Entity entity); - public boolean isSpawnedPet(Entity entity); - public void addSpawnedMob(Entity entity); - public void addSpawnedPet(Entity entity); - public void removeSpawnedMob(Entity entity); - public void removeSpawnedPet(Entity entity); - public void cleanMobLists(); } diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkStore.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkStore.java index 69ed58485..4b1491497 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkStore.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkStore.java @@ -73,15 +73,4 @@ public interface ChunkStore extends Serializable { * @param otherStore Another ChunkletStore that this one should copy all data from */ public void copyFrom(ChunkletStore otherStore); - - public boolean isSpawnedMob(UUID id); - public boolean isSpawnedPet(UUID id); - public void addSpawnedMob(UUID id); - public void addSpawnedPet(UUID id); - public void removeSpawnedMob(UUID id); - public void removeSpawnedPet(UUID id); - public void clearSpawnedMobs(); - public void clearSpawnedPets(); - public List getSpawnedMobs(); - public List getSpawnedPets(); } \ No newline at end of file diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java index 72916cf8a..da06f58b9 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java @@ -25,15 +25,6 @@ public class HashChunkManager implements ChunkManager { public HashMap store = new HashMap(); public ArrayList converters = new ArrayList(); private HashMap oldData = new HashMap(); - // TODO: Investigate whether or not a LinkedList would be faster - private List spawnedMobs = new ArrayList(); - private List mobsToRemove = new ArrayList(); - private List savedChunks = new ArrayList(); - private List checkedMobs = new ArrayList(); - private List removalCheckedMobs = new ArrayList(); - private boolean safeToRemoveMobs = true; - private boolean savingWorld = false; - private boolean iteratingMobs = false; @Override public synchronized void closeAll() { @@ -171,26 +162,6 @@ public class HashChunkManager implements ChunkManager { return; store.put(world.getName() + "," + cx + "," + cz, chunkStore); - - List mobs = chunkStore.getSpawnedMobs(); - - if (mobs.isEmpty()) - return; - - if (entities == null) - entities = world.getChunkAt(cx, cz).getEntities(); - - iteratingMobs = true; - - for (Entity entity : entities) { - if (mobs.contains(entity.getUniqueId())) - addSpawnedMob(entity); - } - - if (safeToRemoveMobs) - iteratingMobs = false; - - chunkStore.clearSpawnedMobs(); } @Override @@ -200,26 +171,6 @@ public class HashChunkManager implements ChunkManager { if (store.containsKey(world.getName() + "," + cx + "," + cz)) { store.remove(world.getName() + "," + cx + "," + cz); - iteratingMobs = true; - - List tempSpawnedMobs = new ArrayList(spawnedMobs); - tempSpawnedMobs.removeAll(removalCheckedMobs); - tempSpawnedMobs.removeAll(checkedMobs); - for (Entity entity : tempSpawnedMobs) { - if (!isEntityInChunk(entity, cx, cz, world)) - continue; - - mobsToRemove.add(entity); - removalCheckedMobs.add(entity); - } - - if (safeToRemoveMobs) { - spawnedMobs.removeAll(mobsToRemove); - mobsToRemove.clear(); - removalCheckedMobs.clear(); - iteratingMobs = false; - } - // closeChunkStore(world, cx, cz); } } @@ -229,71 +180,16 @@ public class HashChunkManager implements ChunkManager { if (world == null) return; - if (savingWorld && savedChunks.contains(world.getName() + "," + cx + "," + cz)) - return; - - boolean unloaded = false; String key = world.getName() + "," + cx + "," + cz; - if (!store.containsKey(key)) { - List tempSpawnedMobs = new ArrayList(spawnedMobs); - tempSpawnedMobs.removeAll(checkedMobs); - for (Entity entity : tempSpawnedMobs) { - if (!isEntityInChunk(entity, cx, cz, world)) - continue; - - loadChunk(cx, cz, world, null); - unloaded = true; - break; - } - } - - if (!store.containsKey(key) && unloaded) { - ChunkStore cStore = ChunkStoreFactory.getChunkStore(world, cx, cz); - store.put(world.getName() + "," + cx + "," + cz, cStore); - } - if (store.containsKey(key)) { ChunkStore out = store.get(world.getName() + "," + cx + "," + cz); - List tempSpawnedMobs = new ArrayList(spawnedMobs); - tempSpawnedMobs.removeAll(checkedMobs); - for (Entity entity : tempSpawnedMobs) { - if (!isEntityInChunk(entity, cx, cz, world)) - continue; - - out.addSpawnedMob(entity.getUniqueId()); - checkedMobs.add(entity); - } - if (!out.isDirty()) return; writeChunkStore(world, cx, cz, out); } - - if(savingWorld) - savedChunks.add(world.getName() + "," + cx + "," + cz); - else - checkedMobs.clear(); - } - - private boolean isEntityInChunk(Entity entity, int cx, int cz, World world) { - if (entity == null || world == null) - return false; - - Chunk chunk = entity.getLocation().getChunk(); - - if (chunk.getX() != cx) - return false; - - if (chunk.getZ() != cz) - return false; - - if (entity.getWorld() != world) - return false; - - return true; } @Override @@ -322,7 +218,6 @@ public class HashChunkManager implements ChunkManager { closeAll(); String worldName = world.getName(); - savingWorld = true; List keys = new ArrayList(store.keySet()); for (String key : keys) { @@ -341,24 +236,6 @@ public class HashChunkManager implements ChunkManager { saveChunk(cx, cz, world); } } - - List tempSpawnedMobs = new ArrayList(spawnedMobs); - tempSpawnedMobs.removeAll(checkedMobs); - for (Entity entity : tempSpawnedMobs) { - World entityWorld = entity.getWorld(); - - if (world != entityWorld) - continue; - - int cx = entity.getLocation().getChunk().getX(); - int cz = entity.getLocation().getChunk().getZ(); - - saveChunk(cx, cz, world); - } - - savingWorld = false; - savedChunks.clear(); - checkedMobs.clear(); } @Override @@ -368,7 +245,6 @@ public class HashChunkManager implements ChunkManager { closeAll(); String worldName = world.getName(); - savingWorld = true; List keys = new ArrayList(store.keySet()); for (String key : keys) { @@ -387,32 +263,6 @@ public class HashChunkManager implements ChunkManager { unloadChunk(cx, cz, world); } } - - safeToRemoveMobs = false; - - List tempSpawnedMobs = new ArrayList(spawnedMobs); - tempSpawnedMobs.removeAll(checkedMobs); - tempSpawnedMobs.removeAll(removalCheckedMobs); - for (Entity entity : tempSpawnedMobs) { - World entityWorld = entity.getWorld(); - - if (world != entityWorld) - continue; - - int cx = entity.getLocation().getChunk().getX(); - int cz = entity.getLocation().getChunk().getZ(); - - unloadChunk(cx, cz, world); - } - - safeToRemoveMobs = true; - - spawnedMobs.removeAll(mobsToRemove); - mobsToRemove.clear(); - checkedMobs.clear(); - removalCheckedMobs.clear(); - savingWorld = false; - savedChunks.clear(); } @Override @@ -575,56 +425,4 @@ public class HashChunkManager implements ChunkManager { return true; } - - @Override - public boolean isSpawnedMob(Entity entity) { - return spawnedMobs.contains(entity); - } - - @Override - public boolean isSpawnedPet(Entity entity) { - return spawnedMobs.contains(entity); - } - - @Override - public void addSpawnedMob(Entity entity) { - if (!isSpawnedMob(entity)) - spawnedMobs.add(entity); - } - - @Override - public void addSpawnedPet(Entity entity) { - if (!isSpawnedMob(entity)) - spawnedMobs.add(entity); - } - - @Override - public void removeSpawnedMob(Entity entity) { - if (isSpawnedMob(entity)) - spawnedMobs.remove(entity); - } - - @Override - public void removeSpawnedPet(Entity entity) { - if (isSpawnedMob(entity)) - spawnedMobs.remove(entity); - } - - @Override - public synchronized void cleanMobLists() { - if (!safeToRemoveMobs || iteratingMobs) - return; - - mobsToRemove.clear(); - - List tempSpawnedMobs = new ArrayList(spawnedMobs); - for (Entity entity : tempSpawnedMobs) { - if (!entity.isValid()) { - mobsToRemove.add(entity); - } - } - - spawnedMobs.removeAll(mobsToRemove); - mobsToRemove.clear(); - } } diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/NullChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/NullChunkManager.java index e3e3b776e..96d91b943 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/NullChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/NullChunkManager.java @@ -87,19 +87,4 @@ public class NullChunkManager implements ChunkManager { @Override public void cleanUp() {} - - @Override - public boolean isSpawnedMob(Entity entity) {return false;} - @Override - public boolean isSpawnedPet(Entity entity) {return false;} - @Override - public void addSpawnedMob(Entity entity) {} - @Override - public void addSpawnedPet(Entity entity) {} - @Override - public void removeSpawnedMob(Entity entity) {} - @Override - public void removeSpawnedPet(Entity entity) {} - @Override - public synchronized void cleanMobLists() {} } \ No newline at end of file diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/PrimitiveChunkStore.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/PrimitiveChunkStore.java index 7db8f56e9..b69bcae49 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/PrimitiveChunkStore.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/PrimitiveChunkStore.java @@ -22,7 +22,6 @@ public class PrimitiveChunkStore implements ChunkStore { private int cx; private int cz; private UUID worldUid; - private List spawnedMobs = new ArrayList(); transient private int worldHeight; public PrimitiveChunkStore(World world, int cx, int cz) { @@ -94,74 +93,6 @@ public class PrimitiveChunkStore implements ChunkStore { dirty = true; } - @Override - public boolean isSpawnedMob(UUID id) { - return spawnedMobs.contains(id); - } - - @Override - public boolean isSpawnedPet(UUID id) { - return spawnedMobs.contains(id); - } - - @Override - public void addSpawnedMob(UUID id) { - if (!isSpawnedMob(id)) { - spawnedMobs.add(id); - dirty = true; - } - } - - @Override - public void addSpawnedPet(UUID id) { - if (!isSpawnedPet(id)) { - spawnedMobs.add(id); - dirty = true; - } - } - - @Override - public void removeSpawnedMob(UUID id) { - if (isSpawnedMob(id)) { - spawnedMobs.remove(id); - dirty = true; - } - } - - @Override - public void removeSpawnedPet(UUID id) { - if (isSpawnedPet(id)) { - spawnedMobs.remove(id); - dirty = true; - } - } - - @Override - public void clearSpawnedMobs() { - if (!spawnedMobs.isEmpty()) { - spawnedMobs.clear(); - dirty = true; - } - } - - @Override - public void clearSpawnedPets() { - if (!spawnedMobs.isEmpty()) { - spawnedMobs.clear(); - dirty = true; - } - } - - @Override - public List getSpawnedMobs() { - return spawnedMobs; - } - - @Override - public List getSpawnedPets() { - return spawnedMobs; - } - private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(MAGIC_NUMBER); out.writeInt(CURRENT_VERSION); @@ -172,8 +103,6 @@ public class PrimitiveChunkStore implements ChunkStore { out.writeInt(cz); out.writeObject(store); - out.writeObject(spawnedMobs); - dirty = false; } @@ -199,25 +128,10 @@ public class PrimitiveChunkStore implements ChunkStore { store = (boolean[][][]) in.readObject(); - if (fileVersionNumber < CURRENT_VERSION) { - if (fileVersionNumber < 5) - fixArray(); - if (fileVersionNumber < 6) { - spawnedMobs = new ArrayList(); - } + if (fileVersionNumber < 5) { + fixArray(); dirty = true; } - - if (fileVersionNumber == 6) { - //What do we want to do about this? These casts are unchecked. - spawnedMobs = (ArrayList) in.readObject(); - List spawnedPets = (ArrayList) in.readObject(); - spawnedMobs.addAll(spawnedPets); - } - - if(fileVersionNumber >= 7) { - spawnedMobs = (ArrayList) in.readObject(); - } } private void fixArray() {