Browse Source

Converting entity tracking to use Bukkit metadata. Should greatly reduce lag on chunk loading and unloading.

Glitchfinder 12 years ago
parent
commit
519485f155

+ 7 - 6
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);
         }
     }
 

+ 0 - 19
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;
-            }
-        }
-    }
 }

+ 6 - 3
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) {

+ 0 - 38
src/main/java/com/gmail/nossr50/runnables/MobStoreCleaner.java

@@ -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();
-    }
-}

+ 1 - 1
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);
 

+ 4 - 1
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;
         }
 

+ 2 - 2
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();
                 }

+ 0 - 8
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();
 }

+ 0 - 11
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<UUID> getSpawnedMobs();
-    public List<UUID> getSpawnedPets();
 }

+ 0 - 202
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java

@@ -25,15 +25,6 @@ public class HashChunkManager implements ChunkManager {
     public HashMap<String, ChunkStore> store = new HashMap<String, ChunkStore>();
     public ArrayList<BlockStoreConversionZDirectory> converters = new ArrayList<BlockStoreConversionZDirectory>();
     private HashMap<UUID, Boolean> oldData = new HashMap<UUID, Boolean>();
-    // TODO: Investigate whether or not a LinkedList would be faster
-    private List<Entity> spawnedMobs = new ArrayList<Entity>();
-    private List<Entity> mobsToRemove = new ArrayList<Entity>();
-    private List<String> savedChunks = new ArrayList<String>();
-    private List<Entity> checkedMobs = new ArrayList<Entity>();
-    private List<Entity> removalCheckedMobs = new ArrayList<Entity>();
-    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<UUID> 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<Entity> tempSpawnedMobs = new ArrayList<Entity>(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<Entity> tempSpawnedMobs = new ArrayList<Entity>(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<Entity> tempSpawnedMobs = new ArrayList<Entity>(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<String> keys = new ArrayList<String>(store.keySet());
         for (String key : keys) {
@@ -341,24 +236,6 @@ public class HashChunkManager implements ChunkManager {
                 saveChunk(cx, cz, world);
             }
         }
-
-        List<Entity> tempSpawnedMobs = new ArrayList<Entity>(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<String> keys = new ArrayList<String>(store.keySet());
         for (String key : keys) {
@@ -387,32 +263,6 @@ public class HashChunkManager implements ChunkManager {
                 unloadChunk(cx, cz, world);
             }
         }
-
-        safeToRemoveMobs = false;
-
-        List<Entity> tempSpawnedMobs = new ArrayList<Entity>(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<Entity> tempSpawnedMobs = new ArrayList<Entity>(spawnedMobs);
-        for (Entity entity : tempSpawnedMobs) {
-            if (!entity.isValid()) {
-                mobsToRemove.add(entity);
-            }
-        }
-
-        spawnedMobs.removeAll(mobsToRemove);
-        mobsToRemove.clear();
-    }
 }

+ 0 - 15
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() {}
 }

+ 2 - 88
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<UUID> spawnedMobs = new ArrayList<UUID>();
     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<UUID> getSpawnedMobs() {
-        return spawnedMobs;
-    }
-
-    @Override
-    public List<UUID> 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<UUID>();
-            }
+        if (fileVersionNumber < 5) {
+            fixArray();
             dirty = true;
         }
-
-        if (fileVersionNumber == 6) {
-            //What do we want to do about this? These casts are unchecked.
-            spawnedMobs = (ArrayList<UUID>) in.readObject();
-            List<UUID> spawnedPets = (ArrayList<UUID>) in.readObject();
-            spawnedMobs.addAll(spawnedPets);
-        }
-
-        if(fileVersionNumber >= 7) {
-            spawnedMobs = (ArrayList<UUID>) in.readObject();
-        }
     }
 
     private void fixArray() {