diff --git a/src/main/java/net/minecraft/world/WorldServer.java b/src/main/java/net/minecraft/world/WorldServer.java index 2c7d8f1..5477599 100644 --- a/src/main/java/net/minecraft/world/WorldServer.java +++ b/src/main/java/net/minecraft/world/WorldServer.java @@ -71,6 +71,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.ultramine.server.chunk.ChunkHash; +import org.ultramine.server.chunk.PendingBlockUpdate; public class WorldServer extends World { @@ -327,6 +328,8 @@ this.theProfiler.startSection("getChunk"); Chunk chunk = this.getChunkFromChunkCoords(chunkX, chunkZ); + this.theProfiler.startSection("updatePending"); + this.updatePendingOf(chunk); this.func_147467_a(k, l, chunk); this.theProfiler.endStartSection("tickChunk"); //Limits and evenly distributes the lighting update time @@ -420,8 +423,7 @@ public boolean isBlockTickScheduledThisTick(int p_147477_1_, int p_147477_2_, int p_147477_3_, Block p_147477_4_) { - NextTickListEntry nextticklistentry = new NextTickListEntry(p_147477_1_, p_147477_2_, p_147477_3_, p_147477_4_); - return this.pendingTickListEntriesThisTick.contains(nextticklistentry); + return false; } public void scheduleBlockUpdate(int p_147464_1_, int p_147464_2_, int p_147464_3_, Block p_147464_4_, int p_147464_5_) @@ -429,67 +431,48 @@ this.scheduleBlockUpdateWithPriority(p_147464_1_, p_147464_2_, p_147464_3_, p_147464_4_, p_147464_5_, 0); } - public void scheduleBlockUpdateWithPriority(int p_147454_1_, int p_147454_2_, int p_147454_3_, Block p_147454_4_, int p_147454_5_, int p_147454_6_) + public void scheduleBlockUpdateWithPriority(int x, int y, int z, Block block, int time, int priority) { - NextTickListEntry nextticklistentry = new NextTickListEntry(p_147454_1_, p_147454_2_, p_147454_3_, p_147454_4_); + //NextTickListEntry nextticklistentry = new NextTickListEntry(x, y, z, block); //Keeping here as a note for future when it may be restored. //boolean isForced = getPersistentChunks().containsKey(new ChunkCoordIntPair(nextticklistentry.xCoord >> 4, nextticklistentry.zCoord >> 4)); //byte b0 = isForced ? 0 : 8; byte b0 = 0; - if (this.scheduledUpdatesAreImmediate && p_147454_4_.getMaterial() != Material.air) + if (this.scheduledUpdatesAreImmediate && block.getMaterial() != Material.air) { - if (p_147454_4_.func_149698_L()) + if (block.func_149698_L()) { b0 = 8; - if (this.checkChunksExist(nextticklistentry.xCoord - b0, nextticklistentry.yCoord - b0, nextticklistentry.zCoord - b0, nextticklistentry.xCoord + b0, nextticklistentry.yCoord + b0, nextticklistentry.zCoord + b0)) + if (this.checkChunksExist(x - b0, y - b0, z - b0, x + b0, y + b0, z + b0)) { - Block block1 = this.getBlock(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord); + Block block1 = this.getBlock(x, y, z); - if (block1.getMaterial() != Material.air && block1 == nextticklistentry.func_151351_a()) + if (block1.getMaterial() != Material.air && block1 == block) { - block1.updateTick(this, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, this.rand); + block1.updateTick(this, x, y, z, this.rand); } } return; } - p_147454_5_ = 1; + time = 1; } + + Chunk chunk = getChunkIfExists(x >> 4, z >> 4); - if (this.checkChunksExist(p_147454_1_ - b0, p_147454_2_ - b0, p_147454_3_ - b0, p_147454_1_ + b0, p_147454_2_ + b0, p_147454_3_ + b0)) + if (chunk != null) { - if (p_147454_4_.getMaterial() != Material.air) - { - nextticklistentry.setScheduledTime((long)p_147454_5_ + this.worldInfo.getWorldTotalTime()); - nextticklistentry.setPriority(p_147454_6_); - } - - if (!this.pendingTickListEntriesHashSet.contains(nextticklistentry)) - { - this.pendingTickListEntriesHashSet.add(nextticklistentry); - this.pendingTickListEntriesTreeSet.add(nextticklistentry); - } + PendingBlockUpdate p = new PendingBlockUpdate(x&15, y, z&15, block, worldInfo.getWorldTotalTime() + (long)time, priority); + chunk.scheduleBlockUpdate(p, true); } } public void func_147446_b(int p_147446_1_, int p_147446_2_, int p_147446_3_, Block p_147446_4_, int p_147446_5_, int p_147446_6_) { - NextTickListEntry nextticklistentry = new NextTickListEntry(p_147446_1_, p_147446_2_, p_147446_3_, p_147446_4_); - nextticklistentry.setPriority(p_147446_6_); - - if (p_147446_4_.getMaterial() != Material.air) - { - nextticklistentry.setScheduledTime((long)p_147446_5_ + this.worldInfo.getWorldTotalTime()); - } - - if (!this.pendingTickListEntriesHashSet.contains(nextticklistentry)) - { - this.pendingTickListEntriesHashSet.add(nextticklistentry); - this.pendingTickListEntriesTreeSet.add(nextticklistentry); - } + } public void updateEntities() @@ -516,148 +499,12 @@ public boolean tickUpdates(boolean par1) { - int i = this.pendingTickListEntriesTreeSet.size(); - - if (i != this.pendingTickListEntriesHashSet.size()) - { - throw new IllegalStateException("TickNextTick list out of synch"); - } - else - { - if (i > 1000) - { - i = 1000; - } - - this.theProfiler.startSection("cleaning"); - NextTickListEntry nextticklistentry; - - for (int j = 0; j < i; ++j) - { - nextticklistentry = (NextTickListEntry)this.pendingTickListEntriesTreeSet.first(); - - if (!par1 && nextticklistentry.scheduledTime > this.worldInfo.getWorldTotalTime()) - { - break; - } - - this.pendingTickListEntriesTreeSet.remove(nextticklistentry); - this.pendingTickListEntriesHashSet.remove(nextticklistentry); -// if(activeChunkSet.containsKey(ChunkHash.chunkToKey(nextticklistentry.xCoord >> 4, nextticklistentry.zCoord >> 4))) -// { - this.pendingTickListEntriesThisTick.add(nextticklistentry); -// } -// else -// { -// i = Math.min(i+1, pendingTickListEntriesTreeSet.size()); -// } - } - - this.theProfiler.endSection(); - this.theProfiler.startSection("ticking"); - Iterator iterator = this.pendingTickListEntriesThisTick.iterator(); - - while (iterator.hasNext()) - { - nextticklistentry = (NextTickListEntry)iterator.next(); - iterator.remove(); - //Keeping here as a note for future when it may be restored. - //boolean isForced = getPersistentChunks().containsKey(new ChunkCoordIntPair(nextticklistentry.xCoord >> 4, nextticklistentry.zCoord >> 4)); - //byte b0 = isForced ? 0 : 8; - byte b0 = 0; - - if (this.checkChunksExist(nextticklistentry.xCoord - b0, nextticklistentry.yCoord - b0, nextticklistentry.zCoord - b0, nextticklistentry.xCoord + b0, nextticklistentry.yCoord + b0, nextticklistentry.zCoord + b0)) - { - Block block = this.getBlock(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord); - - if (block.getMaterial() != Material.air && Block.isEqualTo(block, nextticklistentry.func_151351_a())) - { - try - { - block.updateTick(this, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, this.rand); - } - catch (Throwable throwable1) - { - CrashReport crashreport = CrashReport.makeCrashReport(throwable1, "Exception while ticking a block"); - CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being ticked"); - int k; - - try - { - k = this.getBlockMetadata(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord); - } - catch (Throwable throwable) - { - k = -1; - } - - CrashReportCategory.func_147153_a(crashreportcategory, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, block, k); - throw new ReportedException(crashreport); - } - } - } - else - { - this.scheduleBlockUpdate(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, nextticklistentry.func_151351_a(), 0); - } - } - - this.theProfiler.endSection(); - this.pendingTickListEntriesThisTick.clear(); - return !this.pendingTickListEntriesTreeSet.isEmpty(); - } + return false; } public List getPendingBlockUpdates(Chunk par1Chunk, boolean par2) { - ArrayList arraylist = null; - ChunkCoordIntPair chunkcoordintpair = par1Chunk.getChunkCoordIntPair(); - int i = (chunkcoordintpair.chunkXPos << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.chunkZPos << 4) - 2; - int l = k + 16 + 2; - - for (int i1 = 0; i1 < 2; ++i1) - { - Iterator iterator; - - if (i1 == 0) - { - iterator = this.pendingTickListEntriesTreeSet.iterator(); - } - else - { - iterator = this.pendingTickListEntriesThisTick.iterator(); - - if (!this.pendingTickListEntriesThisTick.isEmpty()) - { - logger.debug("toBeTicked = " + this.pendingTickListEntriesThisTick.size()); - } - } - - while (iterator.hasNext()) - { - NextTickListEntry nextticklistentry = (NextTickListEntry)iterator.next(); - - if (nextticklistentry.xCoord >= i && nextticklistentry.xCoord < j && nextticklistentry.zCoord >= k && nextticklistentry.zCoord < l) - { - if (par2) - { - this.pendingTickListEntriesHashSet.remove(nextticklistentry); - iterator.remove(); - } - - if (arraylist == null) - { - arraylist = new ArrayList(); - } - - arraylist.add(nextticklistentry); - } - } - } - - return arraylist; + return null; } public void updateEntityWithOptionalForce(Entity par1Entity, boolean par2) @@ -1073,4 +920,55 @@ this(); } } + + /* ======================================== ULTRAMINE START =====================================*/ + + public Chunk getChunkIfExists(int cx, int cz) + { + return theChunkProviderServer.getChunkIfExists(cx, cz); + } + + private void updatePendingOf(Chunk chunk) + { + long time = worldInfo.getWorldTotalTime(); + int x = chunk.xPosition << 4; + int z = chunk.zPosition << 4; + + PendingBlockUpdate p; + while((p = chunk.pollPending(time)) != null) + { + updateBlock(x + p.x, p.y, z + p.z, p.getBlock()); + } + } + + private void updateBlock(int x, int y, int z, Block block1) + { + Block block = this.getBlock(x, y, z); + + if (block.getMaterial() != Material.air && Block.isEqualTo(block, block1)) + { + try + { + block.updateTick(this, x, y, z, this.rand); + } + catch (Throwable throwable1) + { + CrashReport crashreport = CrashReport.makeCrashReport(throwable1, "Exception while ticking a block"); + CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being ticked"); + int k; + + try + { + k = this.getBlockMetadata(x, y, z); + } + catch (Throwable throwable) + { + k = -1; + } + + CrashReportCategory.func_147153_a(crashreportcategory, x, y, z, block, k); + throw new ReportedException(crashreport); + } + } + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/world/chunk/Chunk.java b/src/main/java/net/minecraft/world/chunk/Chunk.java index 628eef5..5c9ac1e 100644 --- a/src/main/java/net/minecraft/world/chunk/Chunk.java +++ b/src/main/java/net/minecraft/world/chunk/Chunk.java @@ -8,10 +8,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.Callable; import net.minecraft.block.Block; @@ -40,6 +43,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.ultramine.server.chunk.ChunkHash; +import org.ultramine.server.chunk.PendingBlockUpdate; public class Chunk { @@ -1528,4 +1532,49 @@ /* ======================================== ULTRAMINE START =====================================*/ private final TShortObjectMap fastTileEntityMap = new TShortObjectHashMap(); + + private Set pendingUpdatesSet; + private TreeSet pendingUpdatesQueue; + + public PendingBlockUpdate pollPending(long time) + { + if(pendingUpdatesQueue == null || pendingUpdatesQueue.size() == 0) return null; + + PendingBlockUpdate p = pendingUpdatesQueue.first(); + if(p.scheduledTime <= time) + { + pendingUpdatesSet.remove(p); + pendingUpdatesQueue.remove(p); + + if(pendingUpdatesQueue.size() == 0) + { + pendingUpdatesSet = null; + pendingUpdatesQueue = null; + } + + return p; + } + + return null; + } + + public void scheduleBlockUpdate(PendingBlockUpdate p, boolean check) + { + if(pendingUpdatesQueue == null) + { + pendingUpdatesSet = new HashSet(); + pendingUpdatesQueue = new TreeSet(); + } + + if(!check || !pendingUpdatesSet.contains(p)) + { + pendingUpdatesSet.add(p); + pendingUpdatesQueue.add(p); + } + } + + public Set getPendingUpdatesForSave() + { + return pendingUpdatesQueue; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/world/chunk/storage/AnvilChunkLoader.java b/src/main/java/net/minecraft/world/chunk/storage/AnvilChunkLoader.java index 8a4feee..21abc84 100644 --- a/src/main/java/net/minecraft/world/chunk/storage/AnvilChunkLoader.java +++ b/src/main/java/net/minecraft/world/chunk/storage/AnvilChunkLoader.java @@ -35,6 +35,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.ultramine.server.chunk.ChunkHash; +import org.ultramine.server.chunk.PendingBlockUpdate; import cpw.mods.fml.common.FMLLog; @@ -294,27 +295,28 @@ } par3NBTTagCompound.setTag("TileEntities", nbttaglist3); - List list = par2World.getPendingBlockUpdates(par1Chunk, false); - - if (list != null) + + Set set = par1Chunk.getPendingUpdatesForSave(); + if(set != null) { + int x = par1Chunk.xPosition << 4; + int z = par1Chunk.zPosition << 4; + long k = par2World.getTotalWorldTime(); NBTTagList nbttaglist1 = new NBTTagList(); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) + + for(PendingBlockUpdate p : set) { - NextTickListEntry nextticklistentry = (NextTickListEntry)iterator.next(); NBTTagCompound nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setInteger("i", Block.getIdFromBlock(nextticklistentry.func_151351_a())); - nbttagcompound2.setInteger("x", nextticklistentry.xCoord); - nbttagcompound2.setInteger("y", nextticklistentry.yCoord); - nbttagcompound2.setInteger("z", nextticklistentry.zCoord); - nbttagcompound2.setInteger("t", (int)(nextticklistentry.scheduledTime - k)); - nbttagcompound2.setInteger("p", nextticklistentry.priority); + nbttagcompound2.setInteger("i", Block.getIdFromBlock(p.getBlock())); + nbttagcompound2.setInteger("x", x + p.x); + nbttagcompound2.setInteger("y", p.y); + nbttagcompound2.setInteger("z", z + p.z); + nbttagcompound2.setInteger("t", (int)(p.scheduledTime - k)); + nbttagcompound2.setInteger("p", p.priority); nbttaglist1.appendTag(nbttagcompound2); } - + par3NBTTagCompound.setTag("TileTicks", nbttaglist1); } } @@ -438,10 +440,12 @@ if (nbttaglist3 != null) { + long time = par1World.getTotalWorldTime(); for (int j1 = 0; j1 < nbttaglist3.tagCount(); ++j1) { NBTTagCompound nbttagcompound5 = nbttaglist3.getCompoundTagAt(j1); - par1World.func_147446_b(nbttagcompound5.getInteger("x"), nbttagcompound5.getInteger("y"), nbttagcompound5.getInteger("z"), Block.getBlockById(nbttagcompound5.getInteger("i")), nbttagcompound5.getInteger("t"), nbttagcompound5.getInteger("p")); + chunk.scheduleBlockUpdate(new PendingBlockUpdate(nbttagcompound5.getInteger("x")&15, nbttagcompound5.getInteger("y"), nbttagcompound5.getInteger("z")&15, + Block.getBlockById(nbttagcompound5.getInteger("i")), (long)nbttagcompound5.getInteger("t") + time, nbttagcompound5.getInteger("p")), false); } } } diff --git a/src/main/java/org/ultramine/server/chunk/PendingBlockUpdate.java b/src/main/java/org/ultramine/server/chunk/PendingBlockUpdate.java new file mode 100644 index 0000000..adf1b52 --- /dev/null +++ b/src/main/java/org/ultramine/server/chunk/PendingBlockUpdate.java @@ -0,0 +1,63 @@ +package org.ultramine.server.chunk; + +import net.minecraft.block.Block; + +public class PendingBlockUpdate implements Comparable +{ + private static long nextTickEntryID; + + private final Block block; + public final byte x; + public final short y; + public final byte z; + + public final long scheduledTime; + public final int priority; + + private final long id; + private final short hash; + + public PendingBlockUpdate(int x, int y, int z, Block block, long time, int priority) + { + this.id = nextTickEntryID++; + this.x = (byte)x; + this.y = (short)y; + this.z = (byte)z; + this.block = block; + this.scheduledTime = time; + this.priority = priority; + + hash = ChunkHash.chunkCoordToHash(x, y, z); + } + + public boolean equals(Object o) + { + if (!(o instanceof PendingBlockUpdate)) + { + return false; + } + + PendingBlockUpdate p = (PendingBlockUpdate)o; + return this.hash == p.hash && Block.isEqualTo(this.block, p.block); + } + + public int hashCode() + { + return hash; + } + + public int compareTo(PendingBlockUpdate p) + { + return scheduledTime < p.scheduledTime ? -1 : (scheduledTime > p.scheduledTime ? 1 : (priority != p.priority ? priority - p.priority : (id < p.id ? -1 : (id > p.id ? 1 : 0)))); + } + + public String toString() + { + return Block.getIdFromBlock(block) + ": (" + x + ", " + y + ", " + z + "), " + scheduledTime + ", " + priority + ", " + id; + } + + public Block getBlock() + { + return block; + } +}