diff options
author | Travis Watkins <amaranth@ubuntu.com> | 2014-02-10 14:59:44 -0600 |
---|---|---|
committer | Travis Watkins <amaranth@ubuntu.com> | 2014-02-10 15:43:49 -0600 |
commit | 826643c606061a9ee6c5dc7b17aac16c2e1bab56 (patch) | |
tree | c01b9d8693d513aca79ef10ab052a37f0fee64e9 /src/main/java/net | |
parent | 1113d54dae9f55db7ab65d688d62f6521d0f2bb1 (diff) | |
download | craftbukkit-826643c606061a9ee6c5dc7b17aac16c2e1bab56.tar craftbukkit-826643c606061a9ee6c5dc7b17aac16c2e1bab56.tar.gz craftbukkit-826643c606061a9ee6c5dc7b17aac16c2e1bab56.tar.lz craftbukkit-826643c606061a9ee6c5dc7b17aac16c2e1bab56.tar.xz craftbukkit-826643c606061a9ee6c5dc7b17aac16c2e1bab56.zip |
Handle removing entity while ticking. Fixes BUKKIT-1331
If a plugin causes an entity to be removed from the world while the
world is ticking entities the ticking loop gets out of sync and fails due
to trying to go beyond the end of the entity array. To ensure this doesn't
happen we store the loop position as a field so we can fix it up in the
entity remove method just like the tick method does when it removes an
entity.
Diffstat (limited to 'src/main/java/net')
-rw-r--r-- | src/main/java/net/minecraft/server/World.java | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index f850a0f1..419149ed 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -14,7 +14,6 @@ import java.util.concurrent.Callable; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.LongHashSet; -import org.bukkit.craftbukkit.util.UnsafeList; import org.bukkit.generator.ChunkGenerator; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; @@ -71,6 +70,7 @@ public abstract class World implements IBlockAccess { public long ticksPerAnimalSpawns; public long ticksPerMonsterSpawns; public boolean populating; + private int tickPosition; // CraftBukkit end private ArrayList M; private boolean N; @@ -974,7 +974,14 @@ public abstract class World implements IBlockAccess { this.getChunkAt(i, j).b(entity); } - this.entityList.remove(entity); + // CraftBukkit start - Decrement loop variable field if we've already ticked this entity + int index = this.entityList.indexOf(entity); + if (index <= this.tickPosition) { + this.tickPosition--; + } + this.entityList.remove(index); + // CraftBukkit end + this.b(entity); } @@ -1182,10 +1189,11 @@ public abstract class World implements IBlockAccess { this.f.clear(); this.methodProfiler.c("regular"); - for (i = 0; i < this.entityList.size(); ++i) { - entity = (Entity) this.entityList.get(i); + // CraftBukkit start - Use field for loop variable + for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) { + entity = (Entity) this.entityList.get(this.tickPosition); - // CraftBukkit start - Don't tick entities in chunks queued for unload + // Don't tick entities in chunks queued for unload ChunkProviderServer chunkProviderServer = ((WorldServer) this).chunkProviderServer; if (chunkProviderServer.unloadQueue.contains(MathHelper.floor(entity.locX) >> 4, MathHelper.floor(entity.locZ) >> 4)) { continue; @@ -1222,7 +1230,7 @@ public abstract class World implements IBlockAccess { this.getChunkAt(j, k).b(entity); } - this.entityList.remove(i--); + this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable this.b(entity); } |