Implement thread-safe, async-like and not buggy BlockUpdatesTracker
close #320
This commit is contained in:
parent
3359c026df
commit
7114a28fc6
@ -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_)
|
@ -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;
|
||||
}
|
||||
|
||||
- if (!this.pendingTickListEntriesHashSet.contains(nextticklistentry))
|
||||
+ if (this.pendingTickListEntriesHashSet.add(nextticklistentry))
|
||||
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))
|
||||
- {
|
||||
- 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,16 +646,16 @@
|
||||
nextticklistentry.setScheduledTime((long)p_147446_5_ + this.worldInfo.getWorldTotalTime());
|
||||
- }
|
||||
- }
|
||||
+ 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_);
|
||||
}
|
||||
|
||||
- if (!this.pendingTickListEntriesHashSet.contains(nextticklistentry))
|
||||
+ if (this.pendingTickListEntriesHashSet.add(nextticklistentry))
|
||||
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);
|
||||
+ 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);
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
39
src/main/java/kcauldron/BlockCoords.java
Normal file
39
src/main/java/kcauldron/BlockCoords.java
Normal file
@ -0,0 +1,39 @@
|
||||
package kcauldron;
|
||||
|
||||
public class BlockCoords {
|
||||
public final int x, y, z;
|
||||
public final long key;
|
||||
private final int hash;
|
||||
|
||||
public BlockCoords(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
||||
key = ((long) y << 56) | (((long) z & 0xFFFFFFF) << 28) | (x & 0xFFFFFFF);
|
||||
hash = (int) (key ^ (key >>> 32));
|
||||
}
|
||||
|
||||
public BlockCoords(BlockCoords coords) {
|
||||
this.x = coords.x;
|
||||
this.y = coords.y;
|
||||
this.z = coords.z;
|
||||
this.key = coords.key;
|
||||
this.hash = coords.hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (!(obj instanceof BlockCoords))
|
||||
return false;
|
||||
BlockCoords coords = (BlockCoords) obj;
|
||||
return x == coords.x && y == coords.y && z == coords.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
}
|
69
src/main/java/kcauldron/BlockUpdateEntry.java
Normal file
69
src/main/java/kcauldron/BlockUpdateEntry.java
Normal file
@ -0,0 +1,69 @@
|
||||
package kcauldron;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.NextTickListEntry;
|
||||
|
||||
public class BlockUpdateEntry extends BlockCoords implements Comparable<BlockUpdateEntry> {
|
||||
public final int priority;
|
||||
public final long time;
|
||||
public final Block block;
|
||||
public final long id;
|
||||
private NextTickListEntry mcEntry;
|
||||
|
||||
public BlockUpdateEntry(int x, int y, int z, int priority, long time, Block block, long id) {
|
||||
super(x, y, z);
|
||||
this.priority = priority;
|
||||
this.time = time;
|
||||
this.block = block;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public NextTickListEntry asMCEntry() {
|
||||
if (mcEntry == null) {
|
||||
mcEntry = new NextTickListEntry(x, y, z, block);
|
||||
mcEntry.setPriority(priority);
|
||||
mcEntry.setScheduledTime(time);
|
||||
}
|
||||
return mcEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = hash * 31 + priority;
|
||||
hash = hash * 31 + (int) (time | (time >>> 32));
|
||||
hash = hash * 31 + Block.getIdFromBlock(block);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!super.equals(obj))
|
||||
return false;
|
||||
if (!(obj instanceof BlockUpdateEntry))
|
||||
return false;
|
||||
BlockUpdateEntry entry = (BlockUpdateEntry) obj;
|
||||
if (priority != entry.priority)
|
||||
return false;
|
||||
if (time != entry.time)
|
||||
return false;
|
||||
if (block != entry.block)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(BlockUpdateEntry o) {
|
||||
if (o == this) return 0;
|
||||
if (time < o.time)
|
||||
return -1;
|
||||
if (time > o.time)
|
||||
return 1;
|
||||
int diff = priority - o.priority;
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
if (id < o.id) return -1;
|
||||
if (id > o.id) return 1;
|
||||
return 0; // Normally never should happens
|
||||
}
|
||||
}
|
293
src/main/java/kcauldron/BlockUpdatesTracker.java
Normal file
293
src/main/java/kcauldron/BlockUpdatesTracker.java
Normal file
@ -0,0 +1,293 @@
|
||||
package kcauldron;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import gnu.trove.iterator.TLongObjectIterator;
|
||||
import gnu.trove.map.TLongObjectMap;
|
||||
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.NextTickListEntry;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public final class BlockUpdatesTracker implements Iterable<BlockUpdateEntry> {
|
||||
private long lastEntryId = Long.MIN_VALUE;
|
||||
private final WorldServer world;
|
||||
private final NavigableSet<BlockUpdateEntry> sortedTree = new TreeSet<BlockUpdateEntry>();
|
||||
private final TLongObjectMap<BlockUpdateEntry> trackerMap = new TLongObjectHashMap<BlockUpdateEntry>();
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public BlockUpdatesTracker(WorldServer world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public BlockUpdateEntry allocateEntry(int x, int y, int z, int priority, long time, Block block) {
|
||||
return allocateEntry(x, y, z, priority, time, block, true);
|
||||
}
|
||||
|
||||
public BlockUpdateEntry allocateEntry(int x, int y, int z, int priority, long time, Block block,
|
||||
boolean allowChunkTracking) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
Chunk chunk = allowChunkTracking ? world.getChunkIfLoaded(x >> 4, z >> 4) : null;
|
||||
BlockUpdateEntry entry = new BlockUpdateEntry(x, y, z, priority, time, block, lastEntryId++);
|
||||
BlockUpdateEntry oldEntry = trackerMap.remove(entry.key);
|
||||
if (oldEntry != null) {
|
||||
sortedTree.remove(oldEntry);
|
||||
if (chunk != null)
|
||||
chunk.blockUpdates.remove(oldEntry);
|
||||
}
|
||||
trackerMap.put(entry.key, entry);
|
||||
sortedTree.add(entry);
|
||||
if (chunk != null)
|
||||
chunk.blockUpdates.add(entry);
|
||||
return entry;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockUpdateEntry removeEntry(int x, int y, int z) {
|
||||
return removeEntry(x, y, z, true);
|
||||
}
|
||||
|
||||
public BlockUpdateEntry removeEntry(int x, int y, int z, boolean allowChunkTracking) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
Chunk chunk = allowChunkTracking ? world.getChunkIfLoaded(x >> 4, z >> 4) : null;
|
||||
BlockUpdateEntry entry = trackerMap.remove(new BlockCoords(x, y, z).key);
|
||||
if (entry != null) {
|
||||
sortedTree.remove(entry);
|
||||
if (chunk != null)
|
||||
chunk.blockUpdates.remove(entry);
|
||||
}
|
||||
return entry;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockUpdateEntry removeEntry(BlockUpdateEntry entry, boolean allowChunkTracking) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
Chunk chunk = allowChunkTracking ? world.getChunkIfLoaded(entry.x >> 4, entry.z >> 4) : null;
|
||||
trackerMap.remove(entry.key);
|
||||
if (entry != null) {
|
||||
sortedTree.remove(entry);
|
||||
if (chunk != null)
|
||||
chunk.blockUpdates.remove(entry);
|
||||
}
|
||||
return entry;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockUpdateEntry getEntry(int x, int y, int z) {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return trackerMap.get(new BlockCoords(x, y, z).key);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockUpdateEntry peek() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return sortedTree.first();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return trackerMap.isEmpty();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return trackerMap.size();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockUpdateEntry> iterator() {
|
||||
return new Iterator<BlockUpdateEntry>() {
|
||||
private final Iterator<BlockUpdateEntry> iterator = sortedTree.iterator();;
|
||||
private BlockUpdateEntry next;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
next = null;
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockUpdateEntry next() {
|
||||
return next = iterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (next == null)
|
||||
next();
|
||||
if (next != null)
|
||||
removeEntry(next, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final VanillaWrapper wrapper = new VanillaWrapper();
|
||||
public final HashSet<NextTickListEntry> hashSet = new VanillaHashSetWrapper();
|
||||
public final TreeSet<NextTickListEntry> treeSet = new VanillaTreeSetWrapper();
|
||||
|
||||
private final class VanillaWrapper {
|
||||
private Set<NextTickListEntry> add = new HashSet<NextTickListEntry>();
|
||||
private Set<NextTickListEntry> remove = new HashSet<NextTickListEntry>();
|
||||
|
||||
public boolean add(NextTickListEntry e) {
|
||||
if (add.remove(e)) {
|
||||
allocateEntry(e.xCoord, e.yCoord, e.zCoord, e.priority, e.scheduledTime, e.func_151351_a());
|
||||
return true;
|
||||
}
|
||||
return add.add(e);
|
||||
}
|
||||
|
||||
public boolean remove(NextTickListEntry e) {
|
||||
if (remove.remove(e)) {
|
||||
removeEntry(e.xCoord, e.yCoord, e.zCoord);
|
||||
return true;
|
||||
}
|
||||
return remove.add(e);
|
||||
}
|
||||
|
||||
public boolean contains(NextTickListEntry e, boolean allowInterscan) {
|
||||
if (allowInterscan) {
|
||||
if (add.contains(e))
|
||||
return true;
|
||||
if (remove.contains(e))
|
||||
return false;
|
||||
}
|
||||
return getEntry(e.xCoord, e.yCoord, e.zCoord) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private final class VanillaHashSetWrapper extends HashSet<NextTickListEntry> {
|
||||
@Override
|
||||
public Iterator<NextTickListEntry> iterator() {
|
||||
return new Iterator<NextTickListEntry>() {
|
||||
private final TLongObjectIterator<BlockUpdateEntry> iterator = trackerMap.iterator();;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NextTickListEntry next() {
|
||||
iterator.advance();
|
||||
return iterator.value().asMCEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
removeEntry(iterator.value(), true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(NextTickListEntry e) {
|
||||
return wrapper.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return wrapper.remove((NextTickListEntry) o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return wrapper.contains((NextTickListEntry) o, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BlockUpdatesTracker.this.sortedTree.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return BlockUpdatesTracker.this.sortedTree.size();
|
||||
}
|
||||
}
|
||||
|
||||
private final class VanillaTreeSetWrapper extends TreeSet<NextTickListEntry> {
|
||||
@Override
|
||||
public Iterator<NextTickListEntry> iterator() {
|
||||
return new Iterator<NextTickListEntry>() {
|
||||
private final Iterator<BlockUpdateEntry> iterator = sortedTree.iterator();;
|
||||
private BlockUpdateEntry next;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
next = null;
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NextTickListEntry next() {
|
||||
return (next = iterator.next()).asMCEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (next == null)
|
||||
next();
|
||||
if (next != null)
|
||||
removeEntry(next, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(NextTickListEntry e) {
|
||||
return wrapper.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return wrapper.remove((NextTickListEntry) o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return wrapper.contains((NextTickListEntry) o, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BlockUpdatesTracker.this.sortedTree.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return BlockUpdatesTracker.this.sortedTree.size();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user