diff options
Diffstat (limited to 'nms-patches/World.patch')
-rw-r--r-- | nms-patches/World.patch | 560 |
1 files changed, 560 insertions, 0 deletions
diff --git a/nms-patches/World.patch b/nms-patches/World.patch new file mode 100644 index 00000000..03912ea0 --- /dev/null +++ b/nms-patches/World.patch @@ -0,0 +1,560 @@ +--- ../work/decompile-bb26c12b/net/minecraft/server/World.java 2014-11-27 08:59:46.933420825 +1100 ++++ src/main/java/net/minecraft/server/World.java 2014-11-27 08:42:10.132850949 +1100 +@@ -13,6 +13,22 @@ + import java.util.UUID; + import java.util.concurrent.Callable; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.LongHashSet; ++import org.bukkit.generator.ChunkGenerator; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockCanBuildEvent; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++import org.bukkit.event.weather.WeatherChangeEvent; ++import org.bukkit.event.weather.ThunderChangeEvent; ++// CraftBukkit end ++ + public abstract class World implements IBlockAccess { + + protected boolean e; +@@ -47,7 +63,8 @@ + private final Calendar J = Calendar.getInstance(); + public Scoreboard scoreboard = new Scoreboard(); + public final boolean isStatic; +- protected Set chunkTickList = Sets.newHashSet(); ++ // CraftBukkit - longhashset ++ protected LongHashSet chunkTickList = new LongHashSet(); + private int K; + public boolean allowMonsters; + public boolean allowAnimals; +@@ -55,7 +72,39 @@ + private final WorldBorder M; + int[] H; + +- protected World(IDataManager idatamanager, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public ChunkGenerator generator; ++ ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public ArrayList<BlockState> capturedBlockStates= new ArrayList<BlockState>(); ++ public long ticksPerAnimalSpawns; ++ public long ticksPerMonsterSpawns; ++ public boolean populating; ++ private int tickPosition; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public Chunk getChunkIfLoaded(int x, int z) { ++ return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z); ++ } ++ ++ protected World(IDataManager idatamanager, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag, ChunkGenerator gen, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((WorldServer) this, gen, env); ++ this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit ++ this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit ++ // CraftBukkit end ++ + this.K = this.random.nextInt(12000); + this.allowMonsters = true; + this.allowAnimals = true; +@@ -66,6 +115,8 @@ + this.worldProvider = worldprovider; + this.isStatic = flag; + this.M = worldprovider.getWorldBorder(); ++ ++ this.getServer().addWorld(this.world); // CraftBukkit + } + + public World b() { +@@ -184,6 +235,27 @@ + } + + public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ BlockState blockstate = null; ++ Iterator<BlockState> it = capturedBlockStates.iterator(); ++ while (it.hasNext()) { ++ BlockState previous = it.next(); ++ if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { ++ blockstate = previous; ++ it.remove(); ++ break; ++ } ++ } ++ if (blockstate == null) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockState.getBlockState(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), i); ++ } ++ blockstate.setTypeId(CraftMagicNumbers.getId(iblockdata.getBlock())); ++ blockstate.setRawData((byte) iblockdata.getBlock().toLegacyData(iblockdata)); ++ this.capturedBlockStates.add(blockstate); ++ return true; ++ } ++ // CraftBukkit end + if (!this.isValidLocation(blockposition)) { + return false; + } else if (!this.isStatic && this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { +@@ -191,9 +263,23 @@ + } else { + Chunk chunk = this.getChunkAtWorldCoords(blockposition); + Block block = iblockdata.getBlock(); ++ ++ // CraftBukkit start - capture blockstates ++ BlockState blockstate = null; ++ if (this.captureBlockStates) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockState.getBlockState(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), i); ++ this.capturedBlockStates.add(blockstate); ++ } ++ // CraftBukkit end ++ + IBlockData iblockdata1 = chunk.a(blockposition, iblockdata); + + if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed ++ if (!this.captureBlockStates) { ++ this.capturedBlockStates.remove(blockstate); ++ } ++ // CraftBukkit end + return false; + } else { + Block block1 = iblockdata1.getBlock(); +@@ -204,6 +290,7 @@ + this.methodProfiler.b(); + } + ++ /* + if ((i & 2) != 0 && (!this.isStatic || (i & 4) == 0) && chunk.isReady()) { + this.notify(blockposition); + } +@@ -214,12 +301,35 @@ + this.updateAdjacentComparators(blockposition, block); + } + } ++ */ ++ ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(blockposition, chunk, block1, block, i); ++ } ++ // CraftBukkit end + + return true; + } + } + } + ++ // CraftBukkit start - Split off from original setTypeAndData(int i, int j, int k, Block block, int l, int i1) method in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, Block oldBlock, Block newBLock, int flag) { ++ if ((flag & 2) != 0 && (chunk == null || chunk.isReady())) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.notify(blockposition); ++ } ++ ++ if (!this.isStatic && (flag & 1) != 0) { ++ this.update(blockposition, oldBlock); ++ if (newBLock.isComplexRedstone()) { ++ this.updateAdjacentComparators(blockposition, newBLock); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public boolean setAir(BlockPosition blockposition) { + return this.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 3); + } +@@ -253,6 +363,11 @@ + + public void update(BlockPosition blockposition, Block block) { + if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end + this.applyPhysics(blockposition, block); + } + +@@ -328,6 +443,17 @@ + IBlockData iblockdata = this.getType(blockposition); + + try { ++ // CraftBukkit start ++ CraftWorld world = ((WorldServer) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block)); ++ this.getServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + iblockdata.getBlock().doPhysics(this, blockposition, iblockdata, block); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Exception while updating neighbours"); +@@ -497,6 +623,17 @@ + } + + public IBlockData getType(BlockPosition blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ Iterator<BlockState> it = capturedBlockStates.iterator(); ++ while (it.hasNext()) { ++ BlockState previous = it.next(); ++ if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) { ++ return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); ++ } ++ } ++ } ++ // CraftBukkit end + if (!this.isValidLocation(blockposition)) { + return Blocks.AIR.getBlockData(); + } else { +@@ -704,6 +841,13 @@ + } + + public boolean addEntity(Entity entity) { ++ // CraftBukkit start - Used for entities other than creatures ++ return addEntity(entity, SpawnReason.DEFAULT); ++ } ++ ++ public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason ++ if (entity == null) return false; ++ // CraftBukkit end + int i = MathHelper.floor(entity.locX / 16.0D); + int j = MathHelper.floor(entity.locZ / 16.0D); + boolean flag = entity.attachedToPlayer; +@@ -712,7 +856,35 @@ + flag = true; + } + ++ // CraftBukkit start ++ org.bukkit.event.Cancellable event = null; ++ if (entity instanceof EntityLiving && !(entity instanceof EntityPlayer)) { ++ boolean isAnimal = entity instanceof EntityAnimal || entity instanceof EntityWaterAnimal || entity instanceof EntityGolem; ++ boolean isMonster = entity instanceof EntityMonster || entity instanceof EntityGhast || entity instanceof EntitySlime; ++ ++ if (spawnReason != SpawnReason.CUSTOM) { ++ if (isAnimal && !allowAnimals || isMonster && !allowMonsters) { ++ entity.dead = true; ++ return false; ++ } ++ } ++ ++ event = CraftEventFactory.callCreatureSpawnEvent((EntityLiving) entity, spawnReason); ++ } else if (entity instanceof EntityItem) { ++ event = CraftEventFactory.callItemSpawnEvent((EntityItem) entity); ++ } else if (entity.getBukkitEntity() instanceof org.bukkit.entity.Projectile) { ++ // Not all projectiles extend EntityProjectile, so check for Bukkit interface instead ++ event = CraftEventFactory.callProjectileLaunchEvent(entity); ++ } ++ ++ if (event != null && (event.isCancelled() || entity.dead)) { ++ entity.dead = true; ++ return false; ++ } ++ // CraftBukkit end ++ + if (!flag && !this.isChunkLoaded(i, j, true)) { ++ entity.dead = true; + return false; + } else { + if (entity instanceof EntityHuman) { +@@ -734,6 +906,7 @@ + ((IWorldAccess) this.u.get(i)).a(entity); + } + ++ entity.valid = true; // CraftBukkit + } + + protected void b(Entity entity) { +@@ -741,6 +914,7 @@ + ((IWorldAccess) this.u.get(i)).b(entity); + } + ++ entity.valid = false; // CraftBukkit + } + + public void kill(Entity entity) { +@@ -775,7 +949,15 @@ + 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 != -1) { ++ if (index <= this.tickPosition) { ++ this.tickPosition--; ++ } ++ this.entityList.remove(index); ++ } ++ // CraftBukkit end + this.b(entity); + } + +@@ -958,6 +1140,11 @@ + + for (i = 0; i < this.k.size(); ++i) { + entity = (Entity) this.k.get(i); ++ // CraftBukkit start - Fixed an NPE ++ if (entity == null) { ++ continue; ++ } ++ // CraftBukkit end + + try { + ++entity.ticksLived; +@@ -1001,8 +1188,10 @@ + this.g.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 end + if (entity.vehicle != null) { + if (!entity.vehicle.dead && entity.vehicle.passenger == entity) { + continue; +@@ -1033,7 +1222,7 @@ + this.getChunkAt(j, k).b(entity); + } + +- this.entityList.remove(i--); ++ this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable + this.b(entity); + } + +@@ -1042,6 +1231,14 @@ + + this.methodProfiler.c("blockEntities"); + this.L = true; ++ // CraftBukkit start - From below, clean up tile entities before ticking them ++ if (!this.b.isEmpty()) { ++ this.tileEntityList.removeAll(this.b); ++ this.h.removeAll(this.b); ++ this.b.clear(); ++ } ++ // CraftBukkit end ++ + Iterator iterator = this.tileEntityList.iterator(); + + while (iterator.hasNext()) { +@@ -1073,11 +1270,13 @@ + } + + this.L = false; ++ /* CraftBukkit start - Moved up + if (!this.b.isEmpty()) { + this.tileEntityList.removeAll(this.b); + this.h.removeAll(this.b); + this.b.clear(); + } ++ */ // CraftBukkit end + + this.methodProfiler.c("pendingBlockEntities"); + if (!this.a.isEmpty()) { +@@ -1085,9 +1284,11 @@ + TileEntity tileentity1 = (TileEntity) this.a.get(l); + + if (!tileentity1.x()) { ++ /* CraftBukkit start - Order matters, moved down + if (!this.h.contains(tileentity1)) { + this.a(tileentity1); + } ++ // CraftBukkit end */ + + if (this.isLoaded(tileentity1.getPosition())) { + this.getChunkAtWorldCoords(tileentity1.getPosition()).a(tileentity1.getPosition(), tileentity1); +@@ -1141,7 +1342,10 @@ + int j = MathHelper.floor(entity.locZ); + byte b0 = 32; + +- if (!flag || this.isAreaLoaded(i - b0, 0, j - b0, i + b0, 0, j + b0, true)) { ++ // CraftBukkit start - Use neighbor cache instead of looking up ++ Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4); ++ if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.isAreaLoaded(i - b0, 0, j - b0, i + b0, 0, j + b0) */) { ++ // CraftBukkit end + entity.P = entity.locX; + entity.Q = entity.locY; + entity.R = entity.locZ; +@@ -1615,7 +1819,13 @@ + --j; + this.worldData.setThunderDuration(j); + if (j <= 0) { +- this.worldData.setThundering(!this.worldData.isThundering()); ++ // CraftBukkit start ++ ThunderChangeEvent thunder = new ThunderChangeEvent(this.getWorld(), !this.worldData.isThundering()); ++ this.getServer().getPluginManager().callEvent(thunder); ++ if (!thunder.isCancelled()) { ++ this.worldData.setThundering(!this.worldData.isThundering()); ++ } ++ // CraftBukkit end + } + } + +@@ -1639,7 +1849,14 @@ + --k; + this.worldData.setWeatherDuration(k); + if (k <= 0) { +- this.worldData.setStorm(!this.worldData.hasStorm()); ++ // CraftBukkit start ++ WeatherChangeEvent weather = new WeatherChangeEvent(this.getWorld(), !this.worldData.hasStorm()); ++ this.getServer().getPluginManager().callEvent(weather); ++ ++ if (!weather.isCancelled()) { ++ this.worldData.setStorm(!this.worldData.hasStorm()); ++ } ++ // CraftBukkit end + } + } + +@@ -1656,7 +1873,7 @@ + } + + protected void D() { +- this.chunkTickList.clear(); ++ // this.chunkTickList.clear(); // CraftBukkit - removed + this.methodProfiler.a("buildList"); + + int i; +@@ -1673,7 +1890,7 @@ + + for (int i1 = -l; i1 <= l; ++i1) { + for (int j1 = -l; j1 <= l; ++j1) { +- this.chunkTickList.add(new ChunkCoordIntPair(i1 + j, j1 + k)); ++ this.chunkTickList.add(org.bukkit.craftbukkit.util.LongHash.toLong(i1 + j, j1 + k)); + } + } + } +@@ -1851,7 +2068,10 @@ + } + + public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition) { +- if (!this.areChunksLoaded(blockposition, 17, false)) { ++ // CraftBukkit start - Use neighbor cache instead of looking up ++ Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ if (chunk == null || !chunk.areNeighborsLoaded(1) /*!this.areChunksLoaded(blockposition, 17, false)*/) { ++ // CraftBukkit end + return false; + } else { + int i = 0; +@@ -2095,8 +2315,17 @@ + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ // CraftBukkit start - Split out persistent check, don't apply it to special persistent mobs ++ if (entity instanceof EntityInsentient) { ++ EntityInsentient entityinsentient = (EntityInsentient) entity; ++ if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { ++ continue; ++ } ++ } + +- if ((!(entity instanceof EntityInsentient) || !((EntityInsentient) entity).isPersistent()) && oclass.isAssignableFrom(entity.getClass())) { ++ if (oclass.isAssignableFrom(entity.getClass())) { ++ // if ((!(entity instanceof EntityInsentient) || !((EntityInsentient) entity).isPersistent()) && oclass.isAssignableFrom(entity.getClass())) { ++ // CraftBukkit end + ++i; + } + } +@@ -2105,12 +2334,17 @@ + } + + public void b(Collection collection) { +- this.entityList.addAll(collection); ++ // CraftBukkit start ++ // this.entityList.addAll(collection); + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +- ++ if (entity == null) { ++ continue; ++ } ++ this.entityList.add(entity); ++ // CraftBukkit end + this.a(entity); + } + +@@ -2124,7 +2358,13 @@ + Block block1 = this.getType(blockposition).getBlock(); + AxisAlignedBB axisalignedbb = flag ? null : block.a(this, blockposition, block.getBlockData()); + +- return axisalignedbb != null && !this.a(axisalignedbb, entity) ? false : (block1.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : block1.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection, itemstack)); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = axisalignedbb != null && !this.a(axisalignedbb, entity) ? false : (block1.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : block1.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection, itemstack)); ++ BlockCanBuildEvent event = new BlockCanBuildEvent(this.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block), defaultReturn); ++ this.getServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end + } + + public int getBlockPower(BlockPosition blockposition, EnumDirection enumdirection) { +@@ -2215,6 +2455,11 @@ + + for (int i = 0; i < this.players.size(); ++i) { + EntityHuman entityhuman1 = (EntityHuman) this.players.get(i); ++ // CraftBukkit start - Fixed an NPE ++ if (entityhuman1 == null || entityhuman1.dead) { ++ continue; ++ } ++ // CraftBukkit end + + if (IEntitySelector.d.apply(entityhuman1)) { + double d5 = entityhuman1.e(d0, d1, d2); +@@ -2269,7 +2514,7 @@ + return null; + } + +- public void checkSession() { ++ public void checkSession() throws ExceptionWorldConflict { // CraftBukkit - added throws + this.dataManager.checkSession(); + } + +@@ -2331,6 +2576,16 @@ + + public void everyoneSleeping() {} + ++ // CraftBukkit start ++ // Calls the method that checks to see if players are sleeping ++ // Called by CraftPlayer.setPermanentSleeping() ++ public void checkSleepStatus() { ++ if (!this.isStatic) { ++ this.everyoneSleeping(); ++ } ++ } ++ // CraftBukkit end ++ + public float h(float f) { + return (this.q + (this.r - this.q) * f) * this.j(f); + } +@@ -2538,6 +2793,6 @@ + int l = j * 16 + 8 - blockposition.getZ(); + short short0 = 128; + +- return k >= -short0 && k <= short0 && l >= -short0 && l <= short0; ++ return k >= -short0 && k <= short0 && l >= -short0 && l <= short0 || !this.keepSpawnInMemory; // CraftBukkit - Added 'this.world.keepSpawnInMemory' + } + } |