Bladeren bron

Merge pull request #396 from Glitchfinder/master

Fixes and Patches
Glitchfinder 12 jaren geleden
bovenliggende
commit
e607e04af4

+ 4 - 0
src/main/java/com/gmail/nossr50/config/Config.java

@@ -447,6 +447,10 @@ public class Config extends ConfigLoader {
     public double getMagmaCubeXP() { return config.getDouble("Experience.Combat.Multiplier.Magma_Cube", 2.0); }
     public double getEnderDragonXP() { return config.getDouble("Experience.Combat.Multiplier.Ender_Dragon", 8.0); }
     public double getIronGolemXP() { return config.getDouble("Experience.Combat.Multiplier.Iron_Golem", 2.0); }
+    public double getGiantXP() { return config.getDouble("Experience.Combat.Multiplier.Giant", 4.0); }
+    public double getWitherXP() { return config.getDouble("Experience.Combat.Multiplier.Wither", 7.0); }
+    public double getWitherSkeletonXP() { return config.getDouble("Experience.Combat.Multiplier.Wither_Skeleton", 4.0); }
+    public double getWitchXP() { return config.getDouble("Experience.Combat.Multiplier.Witch", 4.0); }
 
     /* XP Formula Multiplier */
     public int getFormulaMultiplierCurve() { return config.getInt("Experience.Formula.Curve_Modifier", 20); }

+ 4 - 2
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -184,6 +184,8 @@ public class EntityListener implements Listener {
         entity.setFireTicks(0);
         BleedTimer.remove(entity);
         Archery.arrowRetrievalCheck(entity);
+        mcMMO.p.placeStore.removeSpawnedMob(((Entity) entity));
+        mcMMO.p.placeStore.removeSpawnedPet(((Entity) entity));
     }
 
     /**
@@ -196,7 +198,7 @@ public class EntityListener implements Listener {
         SpawnReason reason = event.getSpawnReason();
 
         if ((reason.equals(SpawnReason.SPAWNER) || reason.equals(SpawnReason.SPAWNER_EGG)) && !Config.getInstance().getExperienceGainsMobspawnersEnabled()) {
-            event.getEntity().setMetadata("mcmmoFromMobSpawner", new FixedMetadataValue(plugin, true));
+            mcMMO.p.placeStore.addSpawnedMob(((Entity) event.getEntity()));
         }
     }
 
@@ -397,7 +399,7 @@ public class EntityListener implements Listener {
 
         if(player.hasMetadata("NPC")) return; // Check if this player is a Citizens NPC
 
-        if (Permissions.getInstance().taming(player) && !event.getEntity().hasMetadata("mcmmoSummoned")) {
+        if (Permissions.getInstance().taming(player) && !mcMMO.p.placeStore.isSpawnedPet((Entity) event.getEntity())) {
             PlayerProfile profile = Users.getProfile(player);
             EntityType type = event.getEntityType();
             int xp = 0;

+ 7 - 0
src/main/java/com/gmail/nossr50/listeners/WorldListener.java

@@ -5,6 +5,7 @@ import java.util.ArrayList;
 
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.Listener;
+import org.bukkit.event.world.ChunkLoadEvent;
 import org.bukkit.event.world.ChunkUnloadEvent;
 import org.bukkit.event.world.WorldInitEvent;
 import org.bukkit.event.world.WorldSaveEvent;
@@ -46,4 +47,10 @@ public class WorldListener implements Listener {
     public void onChunkUnload(ChunkUnloadEvent event) {
         mcMMO.placeStore.chunkUnloaded(event.getChunk().getX(), event.getChunk().getZ(), event.getWorld());
     }
+
+    @EventHandler
+    public void onChunkLoad(ChunkLoadEvent event) {
+        if(event.getChunk().getEntities().length > 0)
+            mcMMO.p.placeStore.loadChunk(event.getChunk().getX(), event.getChunk().getZ(), event.getWorld());
+    }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/taming/CallOfTheWildEventHandler.java

@@ -68,7 +68,7 @@ public class CallOfTheWildEventHandler {
             return;
 
         LivingEntity entity = (LivingEntity) player.getWorld().spawnEntity(player.getLocation(), type);
-        entity.setMetadata("mcmmoSummoned", new FixedMetadataValue(mcMMO.p, true));
+        mcMMO.p.placeStore.addSpawnedPet((Entity) entity);
 
         ((Tameable) entity).setOwner(player);
 

+ 27 - 5
src/main/java/com/gmail/nossr50/util/Combat.java

@@ -10,6 +10,7 @@ import org.bukkit.entity.EntityType;
 import org.bukkit.entity.IronGolem;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
+import org.bukkit.entity.Skeleton;
 import org.bukkit.entity.Tameable;
 import org.bukkit.entity.Wolf;
 import org.bukkit.event.entity.EntityDamageByEntityEvent;
@@ -398,14 +399,18 @@ public class Combat {
                 baseXP = 20 * configInstance.getPlayerVersusPlayerXP();
             }
         }
-        else if (!target.hasMetadata("mcmmoFromMobSpawner")) {
-            if (target instanceof Animals && !target.hasMetadata("mcmmoSummoned")) {
+        else if (!mcMMO.p.placeStore.isSpawnedMob(((Entity) target))) {
+            if (target instanceof Animals && !mcMMO.p.placeStore.isSpawnedPet((Entity) target)) {
                 baseXP = configInstance.getAnimalsXP();
             }
             else {
                 EntityType type = target.getType();
 
                 switch (type) {
+                case BAT:
+                    baseXP = configInstance.getAnimalsXP();
+                    break;
+
                 case BLAZE:
                     baseXP = configInstance.getBlazeXP();
                     break;
@@ -430,6 +435,10 @@ public class Combat {
                     baseXP = configInstance.getGhastXP();
                     break;
 
+                case GIANT:
+                    baseXP = configInstance.getGiantXP();
+                    break;
+
                 case MAGMA_CUBE:
                     baseXP = configInstance.getMagmaCubeXP();
                     break;
@@ -450,9 +459,14 @@ public class Combat {
                     break;
 
                 case SKELETON:
-                    baseXP = configInstance.getSkeletonXP();
-                    break;
-
+                    switch(((Skeleton) target).getSkeletonType()) {
+                    case WITHER:
+                        baseXP = configInstance.getWitherSkeletonXP();
+                        break;
+                    default:
+                        baseXP = configInstance.getSkeletonXP();
+                        break;
+                    }
                 case SLIME:
                     baseXP = configInstance.getSlimeXP();
                     break;
@@ -461,6 +475,14 @@ public class Combat {
                     baseXP = configInstance.getSpiderXP();
                     break;
 
+                case WITCH:
+                    baseXP = configInstance.getWitchXP();
+                    break;
+
+                case WITHER:
+                    baseXP = configInstance.getWitherXP();
+                    break;
+
                 case ZOMBIE:
                     baseXP = configInstance.getZombieXP();
                     break;

+ 8 - 0
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkManager.java

@@ -4,6 +4,7 @@ import java.io.IOException;
 
 import org.bukkit.World;
 import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
 
 public interface ChunkManager {
     public void closeAll();
@@ -165,4 +166,11 @@ 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);
 }

+ 13 - 0
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/ChunkStore.java

@@ -1,6 +1,8 @@
 package com.gmail.nossr50.util.blockmeta.chunkmeta;
 
 import java.io.Serializable;
+import java.util.List;
+import java.util.UUID;
 
 import com.gmail.nossr50.util.blockmeta.ChunkletStore;
 
@@ -71,4 +73,15 @@ 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();
 }

+ 189 - 2
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java

@@ -10,12 +10,16 @@ import java.lang.Integer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.UUID;
 
 import org.bukkit.Bukkit;
 import org.bukkit.World;
 import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
 
+import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.ChunkletUnloader;
 import com.gmail.nossr50.runnables.blockstoreconversion.BlockStoreConversionZDirectory;
 
@@ -26,6 +30,10 @@ 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>();
+    private List<Entity> spawnedMobs = new ArrayList<Entity>();
+    private List<Entity> spawnedPets = new ArrayList<Entity>();
+    private List<Entity> mobsToRemove = new ArrayList<Entity>();
+    private boolean safeToRemoveMobs = true;
 
     @Override
     public synchronized void closeAll() {
@@ -159,6 +167,23 @@ public class HashChunkManager implements ChunkManager {
 
         if(in != null) {
             store.put(world.getName() + "," + cx + "," + cz, in);
+
+            List mobs = in.getSpawnedMobs();
+            List pets = in.getSpawnedPets();
+
+            if(mobs.isEmpty() && pets.isEmpty())
+                return;
+
+            for(LivingEntity entity : world.getLivingEntities()) {
+                if(mobs.contains(entity.getUniqueId()))
+                    addSpawnedMob((Entity) entity);
+
+                if(pets.contains(entity.getUniqueId()))
+                    addSpawnedPet((Entity) entity);
+            }
+
+            in.clearSpawnedMobs();
+            in.clearSpawnedPets();
         }
     }
 
@@ -168,6 +193,26 @@ public class HashChunkManager implements ChunkManager {
 
         if(store.containsKey(world.getName() + "," + cx + "," + cz)) {
             store.remove(world.getName() + "," + cx + "," + cz);
+
+            for(Entity entity : spawnedMobs) {
+                if(!isEntityInChunk(entity, cx, cz, world))
+                    continue;
+
+                mobsToRemove.add(entity);
+            }
+
+            for(Entity entity : spawnedPets) {
+                if(!isEntityInChunk(entity, cx, cz, world))
+                    continue;
+
+                mobsToRemove.add(entity);
+            }
+
+            if(safeToRemoveMobs) {
+                spawnedMobs.remove(mobsToRemove);
+                spawnedPets.remove(mobsToRemove);
+                mobsToRemove.clear();
+            }
         }
     }
 
@@ -176,9 +221,51 @@ public class HashChunkManager implements ChunkManager {
         if(world == null)
             return;
 
+        boolean unloaded = false;
+        if(!store.containsKey(world.getName() + "," + cx + "," + cz)) {
+            for(Entity entity : spawnedMobs) {
+                if(!isEntityInChunk(entity, cx, cz, world))
+                    continue;
+
+                loadChunk(cx, cz, world);
+                unloaded = true;
+                break;
+            }
+
+            if(!unloaded) {
+                for(Entity entity : spawnedPets) {
+                    if(!isEntityInChunk(entity, cx, cz, world))
+                        continue;
+
+                    loadChunk(cx, cz, world);
+                    unloaded = true;
+                    break;
+		}
+            }
+        }
+
+        if(!store.containsKey(world.getName() + "," + cx + "," + cz) && unloaded) {
+            ChunkStore cStore = ChunkStoreFactory.getChunkStore(world, cx, cz);
+            store.put(world.getName() + "," + cx + "," + cz, cStore);
+        }
+
         if(store.containsKey(world.getName() + "," + cx + "," + cz)) {
             ChunkStore out = store.get(world.getName() + "," + cx + "," + cz);
 
+            for(Entity entity : spawnedMobs) {
+                if(!isEntityInChunk(entity, cx, cz, world))
+                    continue;
+
+                out.addSpawnedMob(entity.getUniqueId());
+            }
+
+            for(Entity entity : spawnedPets) {
+                if(!isEntityInChunk(entity, cx, cz, world))
+                    continue;
+
+                out.addSpawnedPet(entity.getUniqueId());
+            }
+
             if(!out.isDirty())
                 return;
 
@@ -186,6 +273,22 @@ public class HashChunkManager implements ChunkManager {
         }
     }
 
+    private boolean isEntityInChunk(Entity entity, int cx, int cz, World world) {
+        if(entity == null || world == null)
+            return false;
+
+        if(entity.getLocation().getChunk().getX() != cx)
+            return false;
+
+        if(entity.getLocation().getChunk().getZ() != cz)
+            return false;
+
+        if(entity.getWorld() != world)
+            return false;
+
+        return true;
+    }
+
     @Override
     public synchronized boolean isChunkLoaded(int cx, int cz, World world) {
         if(world == null)
@@ -224,11 +327,35 @@ public class HashChunkManager implements ChunkManager {
                     cz = Integer.parseInt(info[2]);
                 }
                 catch(Exception e) {
-                    return;
+                    continue;
                 }
                 saveChunk(cx, cz, world);
             }
         }
+
+        for(Entity entity : spawnedMobs) {
+            World entityWorld = entity.getWorld();
+
+            if(world != entityWorld)
+                continue;
+
+            int cx = entity.getLocation().getChunk().getX();
+            int cz = entity.getLocation().getChunk().getZ();
+
+            saveChunk(cx, cz, world);
+        }
+
+        for(Entity entity : spawnedPets) {
+            World entityWorld = entity.getWorld();
+
+            if(world != entityWorld)
+                continue;
+
+            int cx = entity.getLocation().getChunk().getX();
+            int cz = entity.getLocation().getChunk().getZ();
+
+            saveChunk(cx, cz, world);
+        }
     }
 
     @Override
@@ -250,11 +377,43 @@ public class HashChunkManager implements ChunkManager {
                     cz = Integer.parseInt(info[2]);
                 }
                 catch(Exception e) {
-                    return;
+                    continue;
                 }
                 unloadChunk(cx, cz, world);
             }
         }
+
+        safeToRemoveMobs = false;
+
+        for(Entity entity : spawnedMobs) {
+            World entityWorld = entity.getWorld();
+
+            if(world != entityWorld)
+                continue;
+
+            int cx = entity.getLocation().getChunk().getX();
+            int cz = entity.getLocation().getChunk().getZ();
+
+            unloadChunk(cx, cz, world);
+        }
+
+        for(Entity entity : spawnedPets) {
+            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.remove(mobsToRemove);
+        spawnedPets.remove(mobsToRemove);
+        mobsToRemove.clear();
     }
 
     @Override
@@ -415,4 +574,32 @@ public class HashChunkManager implements ChunkManager {
             converters.add(converter);
         }
     }
+
+    public boolean isSpawnedMob(Entity entity) {
+        return spawnedMobs.contains(entity);
+    }
+
+    public boolean isSpawnedPet(Entity entity) {
+        return spawnedPets.contains(entity);
+    }
+
+    public void addSpawnedMob(Entity entity) {
+        if(!isSpawnedMob(entity))
+            spawnedMobs.add(entity);
+    }
+
+    public void addSpawnedPet(Entity entity) {
+        if(!isSpawnedPet(entity))
+            spawnedPets.add(entity);
+    }
+
+    public void removeSpawnedMob(Entity entity) {
+        if(isSpawnedMob(entity))
+            spawnedMobs.remove(entity);
+    }
+
+    public void removeSpawnedPet(Entity entity) {
+        if(isSpawnedPet(entity))
+            spawnedPets.remove(entity);
+    }
 }

+ 8 - 0
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/NullChunkManager.java

@@ -4,6 +4,7 @@ import java.io.IOException;
 
 import org.bukkit.World;
 import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
 
 public class NullChunkManager implements ChunkManager {
 
@@ -86,4 +87,11 @@ public class NullChunkManager implements ChunkManager {
 
     @Override
     public void cleanUp() {}
+
+    public boolean isSpawnedMob(Entity entity) {return false;}
+    public boolean isSpawnedPet(Entity entity) {return false;}
+    public void addSpawnedMob(Entity entity) {}
+    public void addSpawnedPet(Entity entity) {}
+    public void removeSpawnedMob(Entity entity) {}
+    public void removeSpawnedPet(Entity entity) {}
 }

+ 77 - 2
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/PrimitiveChunkStore.java

@@ -3,6 +3,8 @@ package com.gmail.nossr50.util.blockmeta.chunkmeta;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 
 import org.bukkit.World;
@@ -15,11 +17,13 @@ public class PrimitiveChunkStore implements ChunkStore {
     transient private boolean dirty = false;
     /** X, Z, Y */
     public boolean[][][] store;
-    private static final int CURRENT_VERSION = 5;
+    private static final int CURRENT_VERSION = 6;
     private static final int MAGIC_NUMBER = 0xEA5EDEBB;
     private int cx;
     private int cz;
     private UUID worldUid;
+    private List spawnedMobs = new ArrayList<UUID>();
+    private List spawnedPets = new ArrayList<UUID>();
     transient private int worldHeight;
     transient private int xBitShifts;
     transient private int zBitShifts;
@@ -100,6 +104,64 @@ public class PrimitiveChunkStore implements ChunkStore {
         dirty = true;
     }
 
+    public boolean isSpawnedMob(UUID id) {
+        return spawnedMobs.contains(id);
+    }
+
+    public boolean isSpawnedPet(UUID id) {
+        return spawnedPets.contains(id);
+    }
+
+    public void addSpawnedMob(UUID id) {
+        if(!isSpawnedMob(id)) {
+            spawnedMobs.add(id);
+            dirty = true;
+        }
+    }
+
+    public void addSpawnedPet(UUID id) {
+        if(!isSpawnedPet(id)) {
+            spawnedPets.add(id);
+            dirty = true;
+        }
+    }
+
+    public void removeSpawnedMob(UUID id) {
+        if(isSpawnedMob(id)) {
+            spawnedMobs.remove(id);
+            dirty = true;
+        }
+    }
+
+    public void removeSpawnedPet(UUID id) {
+        if(isSpawnedPet(id)) {
+            spawnedPets.remove(id);
+            dirty = true;
+        }
+    }
+
+    public void clearSpawnedMobs() {
+        if(!spawnedMobs.isEmpty()) {
+            spawnedMobs.clear();
+            dirty = true;
+        }
+    }
+
+    public void clearSpawnedPets() {
+        if(!spawnedPets.isEmpty()) {
+            spawnedPets.clear();
+            dirty = true;
+        }
+    }
+
+    public List<UUID> getSpawnedMobs() {
+        return spawnedMobs;
+    }
+
+    public List<UUID> getSpawnedPets() {
+        return spawnedPets;
+    }
+
     private void writeObject(ObjectOutputStream out) throws IOException {
         out.writeInt(MAGIC_NUMBER);
         out.writeInt(CURRENT_VERSION);
@@ -110,6 +172,9 @@ public class PrimitiveChunkStore implements ChunkStore {
         out.writeInt(cz);
         out.writeObject(store);
 
+        out.writeObject(spawnedMobs);
+        out.writeObject(spawnedPets);
+
         dirty = false;
     }
 
@@ -139,9 +204,19 @@ public class PrimitiveChunkStore implements ChunkStore {
         store = (boolean[][][]) in.readObject();
 
         if (fileVersionNumber < CURRENT_VERSION) {
-            fixArray();
+            if(fileVersionNumber < 5)
+                fixArray();
+            if(fileVersionNumber < 6) {
+                spawnedMobs = new ArrayList<UUID>();
+                spawnedPets = new ArrayList<UUID>();
+            }
             dirty = true;
         }
+
+        if(fileVersionNumber >= 6) {
+            spawnedMobs = (ArrayList) in.readObject();
+            spawnedPets = (ArrayList) in.readObject();
+        }
     }
 
     private void fixArray() {

+ 4 - 0
src/main/resources/config.yml

@@ -323,6 +323,10 @@ Experience:
             Slime: 2.0
             Ghast: 3.0
             Iron_Golem: 2.0
+            Giant: 4.0
+            Wither: 7.0
+            Wither_Skeleton: 4.0
+            Witch: 4.0
 #
 #  Settings for commands
 ###