summaryrefslogtreecommitdiffstats
path: root/src/main/java/net
diff options
context:
space:
mode:
authorTravis Watkins <amaranth@ubuntu.com>2014-02-10 14:59:44 -0600
committerTravis Watkins <amaranth@ubuntu.com>2014-02-10 15:43:49 -0600
commit826643c606061a9ee6c5dc7b17aac16c2e1bab56 (patch)
treec01b9d8693d513aca79ef10ab052a37f0fee64e9 /src/main/java/net
parent1113d54dae9f55db7ab65d688d62f6521d0f2bb1 (diff)
downloadcraftbukkit-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.java20
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);
}