3
0

Implement thread-safe, async-like and not buggy BlockUpdatesTracker

close #320
This commit is contained in:
Sergey Shatunov
2016-02-03 10:54:09 +07:00
parent 3359c026df
commit 7114a28fc6
7 changed files with 658 additions and 65 deletions

View File

@ -1,11 +0,0 @@
--- ../src-base/minecraft/net/minecraft/world/NextTickListEntry.java
+++ ../src-work/minecraft/net/minecraft/world/NextTickListEntry.java
@@ -38,7 +38,7 @@
public int hashCode()
{
- return (this.xCoord * 1024 * 1024 + this.zCoord * 1024 + this.yCoord) * 256;
+ return (((yCoord * 31 + xCoord) * 17 + zCoord) * 13 + yCoord) * 7 + Block.getIdFromBlock(field_151352_g);
}
public NextTickListEntry setScheduledTime(long p_77176_1_)

View File

@ -69,6 +69,21 @@
this.mcServer = p_i45284_1_;
this.theEntityTracker = new EntityTracker(this);
this.thePlayerManager = new PlayerManager(this);
@@ -106,12 +129,12 @@
if (this.pendingTickListEntriesHashSet == null)
{
- this.pendingTickListEntriesHashSet = new HashSet();
+ this.pendingTickListEntriesHashSet = blockUpdatesTracker.hashSet;
}
if (this.pendingTickListEntriesTreeSet == null)
{
- this.pendingTickListEntriesTreeSet = new TreeSet();
+ this.pendingTickListEntriesTreeSet = blockUpdatesTracker.treeSet;
}
this.worldTeleporter = new Teleporter(this);
@@ -124,6 +147,47 @@
this.mapStorage.setData("scoreboard", scoreboardsavedata);
}
@ -96,12 +111,12 @@
+
+ if (this.pendingTickListEntriesHashSet == null)
+ {
+ this.pendingTickListEntriesHashSet = new HashSet();
+ this.pendingTickListEntriesHashSet = blockUpdatesTracker.hashSet;
+ }
+
+ if (this.pendingTickListEntriesTreeSet == null)
+ {
+ this.pendingTickListEntriesTreeSet = new TreeSet();
+ this.pendingTickListEntriesTreeSet = blockUpdatesTracker.treeSet;
+ }
+
+ this.worldTeleporter = new org.bukkit.craftbukkit.CraftTravelAgent(this); // CraftBukkit
@ -366,7 +381,7 @@
block.updateTick(this, j2 + k, l2 + extendedblockstorage.getYLocation(), k2 + l, this.rand);
}
}
@@ -396,6 +569,13 @@
@@ -396,12 +569,19 @@
this.theProfiler.endSection();
}
@ -380,33 +395,86 @@
}
public boolean isBlockTickScheduledThisTick(int p_147477_1_, int p_147477_2_, int p_147477_3_, Block p_147477_4_)
@@ -447,10 +627,11 @@
nextticklistentry.setPriority(p_147454_6_);
}
{
- NextTickListEntry nextticklistentry = new NextTickListEntry(p_147477_1_, p_147477_2_, p_147477_3_, p_147477_4_);
- return this.pendingTickListEntriesThisTick.contains(nextticklistentry);
+ for (kcauldron.BlockUpdateEntry entry : (Iterable<kcauldron.BlockUpdateEntry>) pendingTickListEntriesThisTick) if (entry.x == p_147477_1_ && entry.y == p_147477_2_ && entry.z == p_147477_3_ && entry.block == p_147477_4_) return true;
+ 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_)
@@ -411,70 +591,29 @@
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_)
{
- NextTickListEntry nextticklistentry = new NextTickListEntry(p_147454_1_, p_147454_2_, p_147454_3_, p_147454_4_);
- //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 (p_147454_4_.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))
- {
- Block block1 = this.getBlock(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord);
-
- if (block1.getMaterial() != Material.air && block1 == nextticklistentry.func_151351_a())
- {
- block1.updateTick(this, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, this.rand);
- }
+ if (this.scheduledUpdatesAreImmediate && p_147454_4_.getMaterial() != Material.air) {
+ if (p_147454_4_.func_149698_L()) {
+ if (checkChunksExist(p_147454_1_ - 8, p_147454_2_ - 8, p_147454_3_ - 8, p_147454_1_ + 8, p_147454_2_ + 8, p_147454_3_ + 8)) {
+ Block block = getBlock(p_147454_1_, p_147454_2_, p_147454_3_);
+ if (block.getMaterial() != Material.air && block == p_147454_4_)
+ block.updateTick(this, p_147454_1_, p_147454_2_, p_147454_3_, rand);
}
-
return;
}
-
p_147454_5_ = 1;
}
-
- 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 (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))
+ if (this.pendingTickListEntriesHashSet.add(nextticklistentry))
{
- {
- this.pendingTickListEntriesHashSet.add(nextticklistentry);
- this.pendingTickListEntriesTreeSet.add(nextticklistentry);
+
+ if (!this.pendingTickListEntriesTreeSet.add(nextticklistentry)) pendingTickListEntriesHashSet.remove(nextticklistentry); else {
+ Chunk chunk = getChunkIfLoaded(p_147454_1_ >> 4, p_147454_3_ >> 4); if (chunk != null) chunk.blockUpdates.add(nextticklistentry); } // KCauldron
}
}
- }
- }
+ if (getChunkIfLoaded(p_147454_1_ >> 4, p_147454_3_ >> 4) != null)
+ blockUpdatesTracker.allocateEntry(p_147454_1_, p_147454_2_, p_147454_3_, p_147454_6_, p_147454_5_ + this.worldInfo.getWorldTotalTime(), p_147454_4_);
}
@@ -465,16 +646,16 @@
nextticklistentry.setScheduledTime((long)p_147446_5_ + this.worldInfo.getWorldTotalTime());
}
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))
+ if (this.pendingTickListEntriesHashSet.add(nextticklistentry))
{
- {
- this.pendingTickListEntriesHashSet.add(nextticklistentry);
- this.pendingTickListEntriesTreeSet.add(nextticklistentry);
+ if (!this.pendingTickListEntriesTreeSet.add(nextticklistentry)) pendingTickListEntriesHashSet.remove(nextticklistentry); else {
+ Chunk chunk = getChunkIfLoaded(p_147446_1_ >> 4, p_147446_3_ >> 4); if (chunk != null) chunk.blockUpdates.add(nextticklistentry); }
}
- }
+ blockUpdatesTracker.allocateEntry(p_147446_1_, p_147446_2_, p_147446_3_, p_147446_6_, p_147446_5_ + this.worldInfo.getWorldTotalTime(), p_147446_4_);
}
public void updateEntities()
@ -416,7 +484,7 @@
{
if (this.updateEntityTick++ >= 1200)
{
@@ -487,6 +668,7 @@
@@ -487,6 +626,7 @@
}
super.updateEntities();
@ -424,8 +492,24 @@
}
public void resetUpdateEntityTick()
@@ -506,7 +688,16 @@
@@ -496,33 +636,40 @@
public boolean tickUpdates(boolean p_72955_1_)
{
- int i = this.pendingTickListEntriesTreeSet.size();
+ int i = blockUpdatesTracker.size();
- if (i != this.pendingTickListEntriesHashSet.size())
+ //if (i != this.pendingTickListEntriesHashSet.size())
+ //{
+ // throw new IllegalStateException("TickNextTick list out of synch");
+ //}
+ //else
{
- throw new IllegalStateException("TickNextTick list out of synch");
- }
- else
- {
if (i > 1000)
{
- i = 1000;
@ -442,24 +526,114 @@
}
this.theProfiler.startSection("cleaning");
@@ -515,7 +706,7 @@
- NextTickListEntry nextticklistentry;
+ kcauldron.BlockUpdateEntry nextticklistentry;
for (int j = 0; j < i; ++j)
{
nextticklistentry = (NextTickListEntry)this.pendingTickListEntriesTreeSet.first();
- nextticklistentry = (NextTickListEntry)this.pendingTickListEntriesTreeSet.first();
-
+ Chunk chunk = getChunkIfLoaded(nextticklistentry.xCoord >> 4, nextticklistentry.zCoord >> 4);
if (!p_72955_1_ && nextticklistentry.scheduledTime > this.worldInfo.getWorldTotalTime())
- if (!p_72955_1_ && nextticklistentry.scheduledTime > this.worldInfo.getWorldTotalTime())
+ nextticklistentry = blockUpdatesTracker.peek();
+ Chunk chunk = getChunkIfLoaded(nextticklistentry.x >> 4, nextticklistentry.z >> 4);
+ if (!p_72955_1_ && nextticklistentry.time > this.worldInfo.getWorldTotalTime())
{
break;
@@ -523,6 +714,7 @@
this.pendingTickListEntriesTreeSet.remove(nextticklistentry);
this.pendingTickListEntriesHashSet.remove(nextticklistentry);
+ if (chunk != null) chunk.blockUpdates.remove(nextticklistentry); // KCauldron
}
-
- this.pendingTickListEntriesTreeSet.remove(nextticklistentry);
- this.pendingTickListEntriesHashSet.remove(nextticklistentry);
+ blockUpdatesTracker.removeEntry(nextticklistentry, true);
this.pendingTickListEntriesThisTick.add(nextticklistentry);
}
@@ -651,7 +843,37 @@
@@ -532,22 +679,22 @@
while (iterator.hasNext())
{
- nextticklistentry = (NextTickListEntry)iterator.next();
+ nextticklistentry = (kcauldron.BlockUpdateEntry)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))
+ if (this.checkChunksExist(nextticklistentry.x - b0, nextticklistentry.y - b0, nextticklistentry.z - b0, nextticklistentry.x + b0, nextticklistentry.y + b0, nextticklistentry.z + b0))
{
- Block block = this.getBlock(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord);
+ Block block = this.getBlock(nextticklistentry.x, nextticklistentry.y, nextticklistentry.z);
- if (block.getMaterial() != Material.air && Block.isEqualTo(block, nextticklistentry.func_151351_a()))
+ if (block.getMaterial() != Material.air && Block.isEqualTo(block, nextticklistentry.block))
{
try
{
- block.updateTick(this, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, this.rand);
+ block.updateTick(this, nextticklistentry.x, nextticklistentry.y, nextticklistentry.z, this.rand);
}
catch (Throwable throwable1)
{
@@ -557,27 +704,27 @@
try
{
- k = this.getBlockMetadata(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord);
+ k = this.getBlockMetadata(nextticklistentry.x, nextticklistentry.y, nextticklistentry.z);
}
catch (Throwable throwable)
{
k = -1;
}
- CrashReportCategory.func_147153_a(crashreportcategory, nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, block, k);
+ CrashReportCategory.func_147153_a(crashreportcategory, nextticklistentry.x, nextticklistentry.y, nextticklistentry.z, block, k);
throw new ReportedException(crashreport);
}
}
}
else
{
- this.scheduleBlockUpdate(nextticklistentry.xCoord, nextticklistentry.yCoord, nextticklistentry.zCoord, nextticklistentry.func_151351_a(), 0);
+ this.scheduleBlockUpdate(nextticklistentry.x, nextticklistentry.y, nextticklistentry.z, nextticklistentry.block, 0);
}
}
this.theProfiler.endSection();
this.pendingTickListEntriesThisTick.clear();
- return !this.pendingTickListEntriesTreeSet.isEmpty();
+ return !blockUpdatesTracker.isEmpty();
}
}
@@ -596,7 +743,7 @@
if (i1 == 0)
{
- iterator = this.pendingTickListEntriesTreeSet.iterator();
+ iterator = this.blockUpdatesTracker.iterator();
}
else
{
@@ -610,13 +757,13 @@
while (iterator.hasNext())
{
- NextTickListEntry nextticklistentry = (NextTickListEntry)iterator.next();
+ kcauldron.BlockUpdateEntry nextticklistentry = (kcauldron.BlockUpdateEntry)iterator.next();
- if (nextticklistentry.xCoord >= i && nextticklistentry.xCoord < j && nextticklistentry.zCoord >= k && nextticklistentry.zCoord < l)
+ if (nextticklistentry.x >= i && nextticklistentry.x < j && nextticklistentry.z >= k && nextticklistentry.z < l)
{
if (p_72920_2_)
{
- this.pendingTickListEntriesHashSet.remove(nextticklistentry);
+ //this.pendingTickListEntriesHashSet.remove(nextticklistentry);
iterator.remove();
}
@@ -651,7 +798,37 @@
protected IChunkProvider createChunkProvider()
{
IChunkLoader ichunkloader = this.saveHandler.getChunkLoader(this.provider);
@ -498,7 +672,7 @@
return this.theChunkProviderServer;
}
@@ -659,29 +881,31 @@
@@ -659,29 +836,31 @@
{
ArrayList arraylist = new ArrayList();
@ -545,7 +719,26 @@
return arraylist;
}
@@ -733,7 +957,28 @@
@@ -702,14 +881,14 @@
this.entityIdMap = new IntHashMap();
}
- if (this.pendingTickListEntriesHashSet == null)
+ if (this.pendingTickListEntriesHashSet == null && blockUpdatesTracker != null)
{
- this.pendingTickListEntriesHashSet = new HashSet();
+ this.pendingTickListEntriesHashSet = blockUpdatesTracker.hashSet;
}
- if (this.pendingTickListEntriesTreeSet == null)
+ if (this.pendingTickListEntriesTreeSet == null && blockUpdatesTracker != null)
{
- this.pendingTickListEntriesTreeSet = new TreeSet();
+ this.pendingTickListEntriesTreeSet = blockUpdatesTracker.treeSet;
}
this.createSpawnPosition(p_72963_1_);
@@ -733,7 +912,28 @@
int i = 0;
int j = this.provider.getAverageGroundLevel();
int k = 0;
@ -574,7 +767,7 @@
if (chunkposition != null)
{
i = chunkposition.chunkPosX;
@@ -876,6 +1121,20 @@
@@ -876,6 +1076,20 @@
public boolean addWeatherEffect(Entity p_72942_1_)
{
@ -595,7 +788,7 @@
if (super.addWeatherEffect(p_72942_1_))
{
this.mcServer.getConfigurationManager().sendToAllNear(p_72942_1_.posX, p_72942_1_.posY, p_72942_1_.posZ, 512.0D, this.provider.dimensionId, new S2CPacketSpawnGlobalEntity(p_72942_1_));
@@ -894,13 +1153,23 @@
@@ -894,13 +1108,23 @@
public Explosion newExplosion(Entity p_72885_1_, double p_72885_2_, double p_72885_4_, double p_72885_6_, float p_72885_8_, boolean p_72885_9_, boolean p_72885_10_)
{
@ -620,7 +813,7 @@
if (!p_72885_10_)
{
explosion.affectedBlockPositions.clear();
@@ -977,7 +1246,7 @@
@@ -977,7 +1201,7 @@
{
boolean flag = this.isRaining();
super.updateWeather();
@ -629,7 +822,7 @@
if (this.prevRainingStrength != this.rainingStrength)
{
this.mcServer.getConfigurationManager().sendPacketToAllPlayersInDimension(new S2BPacketChangeGameState(7, this.rainingStrength), this.provider.dimensionId);
@@ -988,10 +1257,6 @@
@@ -988,10 +1212,6 @@
this.mcServer.getConfigurationManager().sendPacketToAllPlayersInDimension(new S2BPacketChangeGameState(8, this.thunderingStrength), this.provider.dimensionId);
}
@ -640,7 +833,7 @@
if (flag != this.isRaining())
{
if (flag)
@@ -1006,6 +1271,33 @@
@@ -1006,6 +1226,33 @@
this.mcServer.getConfigurationManager().sendPacketToAllPlayersInDimension(new S2BPacketChangeGameState(7, this.rainingStrength), this.provider.dimensionId);
this.mcServer.getConfigurationManager().sendPacketToAllPlayersInDimension(new S2BPacketChangeGameState(8, this.thunderingStrength), this.provider.dimensionId);
}
@ -674,7 +867,7 @@
}
protected int func_152379_p()
@@ -1069,4 +1361,64 @@
@@ -1069,4 +1316,54 @@
this();
}
}
@ -727,15 +920,5 @@
+ // CraftBukkit end
+
+ // KCauldron start
+ public NextTickListEntry allocateEntry(int x, int y, int z, Block block, int time, int priority)
+ {
+ NextTickListEntry nextticklistentry = new NextTickListEntry(x, y, z, block);
+ nextticklistentry.setPriority(priority);
+ if (block.getMaterial() != Material.air)
+ nextticklistentry.setScheduledTime((long)time + this.worldInfo.getWorldTotalTime());
+ if (this.pendingTickListEntriesHashSet.add(nextticklistentry)) {
+ if (!this.pendingTickListEntriesTreeSet.add(nextticklistentry)) pendingTickListEntriesHashSet.remove(nextticklistentry);
+ }
+ return nextticklistentry;
+ }
+ public final kcauldron.BlockUpdatesTracker blockUpdatesTracker = new kcauldron.BlockUpdatesTracker(this);
}

View File

@ -377,5 +377,5 @@
+ }
+
+ // KCauldron hold block updates into each chunk individually
+ public final java.util.Set<net.minecraft.world.NextTickListEntry> blockUpdates = new java.util.TreeSet<net.minecraft.world.NextTickListEntry>();
+ public final java.util.Set<kcauldron.BlockUpdateEntry> blockUpdates = new java.util.TreeSet<kcauldron.BlockUpdateEntry>();
}

View File

@ -142,6 +142,26 @@
if (list != null)
{
@@ -389,13 +410,13 @@
while (iterator.hasNext())
{
- NextTickListEntry nextticklistentry = (NextTickListEntry)iterator.next();
+ kcauldron.BlockUpdateEntry nextticklistentry = (kcauldron.BlockUpdateEntry)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("i", Block.getIdFromBlock(nextticklistentry.block));
+ nbttagcompound2.setInteger("x", nextticklistentry.x);
+ nbttagcompound2.setInteger("y", nextticklistentry.y);
+ nbttagcompound2.setInteger("z", nextticklistentry.z);
+ nbttagcompound2.setInteger("t", (int)(nextticklistentry.time - k));
nbttagcompound2.setInteger("p", nextticklistentry.priority);
nbttaglist1.appendTag(nbttagcompound2);
}
@@ -455,6 +476,7 @@
public void loadEntities(World p_75823_1_, NBTTagCompound p_75823_2_, Chunk chunk)
@ -232,7 +252,7 @@
{
NBTTagCompound nbttagcompound5 = nbttaglist3.getCompoundTagAt(j1);
- p_75823_1_.func_147446_b(nbttagcompound5.getInteger("x"), nbttagcompound5.getInteger("y"), nbttagcompound5.getInteger("z"), Block.getBlockById(nbttagcompound5.getInteger("i")), nbttagcompound5.getInteger("t"), nbttagcompound5.getInteger("p"));
+ NextTickListEntry entry = ((net.minecraft.world.WorldServer) p_75823_1_).allocateEntry(nbttagcompound5.getInteger("x"), nbttagcompound5.getInteger("y"), nbttagcompound5.getInteger("z"), Block.getBlockById(nbttagcompound5.getInteger("i")), nbttagcompound5.getInteger("t"), nbttagcompound5.getInteger("p"));
+ kcauldron.BlockUpdateEntry entry = ((net.minecraft.world.WorldServer) p_75823_1_).blockUpdatesTracker.allocateEntry(nbttagcompound5.getInteger("x"), nbttagcompound5.getInteger("y"), nbttagcompound5.getInteger("z"), nbttagcompound5.getInteger("p"), nbttagcompound5.getInteger("t"), Block.getBlockById(nbttagcompound5.getInteger("i")));
+ chunk.blockUpdates.add(entry);
}
}