diff --git a/build.gradle b/build.gradle index a43f0e3..1e9e822 100644 --- a/build.gradle +++ b/build.gradle @@ -166,7 +166,7 @@ else { version = "${mcVersion}-${forgeVersion}-${nextRevisionNumber}-${nextBuildNumber}" launch4j { - jreMinVersion = '1.6.0' + jreMinVersion = '1.8.0' } configurations { @@ -213,6 +213,7 @@ dependencies { libraries 'co.aikar:minecraft-timings:1.0.4' libraries 'net.openhft:affinity:3.0.1' libraries 'com.koloboke:koloboke-impl-jdk8:1.0.0' + libraries 'it.unimi.dsi:fastutil:8.2.2' compile 'org.projectlombok:lombok:1.16.18' } diff --git a/patches/net/minecraft/network/NetHandlerPlayServer.java.patch b/patches/net/minecraft/network/NetHandlerPlayServer.java.patch index 9fa1b47..6045a04 100644 --- a/patches/net/minecraft/network/NetHandlerPlayServer.java.patch +++ b/patches/net/minecraft/network/NetHandlerPlayServer.java.patch @@ -277,8 +277,8 @@ + + trigger = !trigger; + if(trigger) -+ this.server.getPluginManager().callEvent(event); -+ ++ this.server.getPluginManager().callEvent(event); ++ + // If the event is cancelled we move the player back to their old location. + if (event.isCancelled()) + { @@ -724,35 +724,35 @@ + } + else if (true) + { -+ String[] bits = s.split(" "); -+ -+ HashSet possibilities = new HashSet(); // No duplicates allowed -+ for (String str: bits) -+ { -+ if (str.length() <= 17 && str.length() >= 4) -+ { -+ if(str.charAt(0) != '@') -+ continue; -+ possibilities.add(str.substring(1)); ++ String[] bits = s.split(" "); ++ ++ HashSet possibilities = new HashSet(); // No duplicates allowed ++ for (String str: bits) ++ { ++ if (str.length() <= 17 && str.length() >= 4) ++ { ++ if(str.charAt(0) != '@') ++ continue; ++ possibilities.add(str.substring(1)); - this.chatSpamThresholdCount += 20; -+ } -+ } -+ -+ for (Object o : MinecraftServer.getServer().getConfigurationManager().playerEntityList) -+ { -+ if (! (o instanceof EntityPlayerMP)) -+ { -+ continue; -+ } -+ EntityPlayerMP ep = (EntityPlayerMP)o; -+ if (possibilities.contains(ep.getCommandSenderName())) -+ { -+ ep.worldObj.playSoundAtEntity(ep, "random.orb", 4.0F, 4.0F); -+ } -+ -+ } -+ ++ } ++ } ++ ++ for (Object o : MinecraftServer.getServer().getConfigurationManager().playerEntityList) ++ { ++ if (! (o instanceof EntityPlayerMP)) ++ { ++ continue; ++ } ++ EntityPlayerMP ep = (EntityPlayerMP)o; ++ if (possibilities.contains(ep.getCommandSenderName())) ++ { ++ ep.worldObj.playSoundAtEntity(ep, "random.orb", 4.0F, 4.0F); ++ } ++ ++ } ++ + this.chat(s, true); + // CraftBukkit end - the below is for reference. :) + } @@ -939,10 +939,10 @@ + + if (net.minecraftforge.cauldron.configuration.CauldronConfig.instance.noFallbackAlias.getValue()) + { -+ int ind = p_147361_1_.indexOf(':'); -+ int spc = p_147361_1_.indexOf(' '); -+ if (ind != -1 && ( ind < spc || spc == -1)) -+ p_147361_1_ = "/" + p_147361_1_.substring(ind); ++ int ind = p_147361_1_.indexOf(':'); ++ int spc = p_147361_1_.indexOf(' '); ++ if (ind != -1 && ( ind < spc || spc == -1)) ++ p_147361_1_ = "/" + p_147361_1_.substring(ind); + } + + PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, p_147361_1_, new LazyPlayerSet()); @@ -1212,7 +1212,7 @@ + else + // not coming from end + { -+ this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, false, null, isDead); ++ this.playerEntity = this.serverController.getConfigurationManager().respawnPlayer(this.playerEntity, 0, false, null, isDead); + } + // Cauldron end + } diff --git a/patches/net/minecraft/world/World.java.patch b/patches/net/minecraft/world/World.java.patch index 3fdba79..472ee4a 100644 --- a/patches/net/minecraft/world/World.java.patch +++ b/patches/net/minecraft/world/World.java.patch @@ -581,7 +581,7 @@ + } + } + ChunkProviderServer cps = (ChunkProviderServer) this.chunkProvider; -+ return cps.loadedChunkHashMap_KC.rawThermos().bulkCheck(st); ++ return cps.loadedChunkHashMap_KC.rawThermosMap().bulkCheck(st); + } + } + else diff --git a/patches/net/minecraft/world/gen/ChunkProviderServer.java.patch b/patches/net/minecraft/world/gen/ChunkProviderServer.java.patch index 972d001..6a38a39 100644 --- a/patches/net/minecraft/world/gen/ChunkProviderServer.java.patch +++ b/patches/net/minecraft/world/gen/ChunkProviderServer.java.patch @@ -100,7 +100,7 @@ public boolean chunkExists(int p_73149_1_, int p_73149_2_) { - return this.loadedChunkHashMap.containsItem(ChunkCoordIntPair.chunkXZ2Int(p_73149_1_, p_73149_2_)); -+ return this.loadedChunkHashMap_KC.rawThermos().get(p_73149_1_, p_73149_2_) != null; //Thermos Replacement ++ return this.loadedChunkHashMap_KC.rawThermosMap().get(p_73149_1_, p_73149_2_) != null; //Thermos Replacement } - public List func_152380_a() @@ -112,7 +112,7 @@ public void unloadChunksIfNotNearSpawn(int p_73241_1_, int p_73241_2_) { + // PaperSpigot start - Asynchronous lighting updates -+ Chunk chunk = this.loadedChunkHashMap_KC.rawThermos().get(p_73241_1_, p_73241_2_); //Thermos replacement ++ Chunk chunk = this.loadedChunkHashMap_KC.rawThermosMap().get(p_73241_1_, p_73241_2_); //Thermos replacement + // Thermos don't light modded chunks + boolean modFlag = false; + try { if (chunk.worldObj.isModded == null) chunk.worldObj.isModded = false; modFlag = chunk.worldObj.isModded;} catch(Exception e){} @@ -133,7 +133,7 @@ { - this.chunksToUnload.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_73241_1_, p_73241_2_))); + this.chunksToUnload.add(p_73241_1_, p_73241_2_); -+ Chunk c = (this.loadedChunkHashMap_KC.rawThermos().get(p_73241_1_, p_73241_2_)); //Thermos replacement ++ Chunk c = (this.loadedChunkHashMap_KC.rawThermosMap().get(p_73241_1_, p_73241_2_)); //Thermos replacement + + if (c != null) + { @@ -149,7 +149,7 @@ - this.chunksToUnload.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_73241_1_, p_73241_2_))); + // CraftBukkit start + this.chunksToUnload.add(p_73241_1_, p_73241_2_); -+ Chunk c = (this.loadedChunkHashMap_KC.rawThermos().get(p_73241_1_, p_73241_2_)); //KCauldron replacement ++ Chunk c = (this.loadedChunkHashMap_KC.rawThermosMap().get(p_73241_1_, p_73241_2_)); //KCauldron replacement + + if (c != null) + { @@ -175,7 +175,7 @@ - this.unloadChunksIfNotNearSpawn(chunk.xPosition, chunk.zPosition); - } + public Chunk getChunkIfLoaded(int x, int z) { -+ return this.loadedChunkHashMap_KC.rawThermos().get(x,z); //Thermos replacement ++ return this.loadedChunkHashMap_KC.rawThermosMap().get(x,z); //Thermos replacement } public Chunk loadChunk(int p_73158_1_, int p_73158_2_) @@ -187,7 +187,7 @@ - this.chunksToUnload.remove(Long.valueOf(k)); - Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(k); + this.chunksToUnload.remove(par1, par2); -+ Chunk chunk = this.loadedChunkHashMap_KC.rawThermos().get(par1,par2); //Thermos replacement ++ Chunk chunk = this.loadedChunkHashMap_KC.rawThermosMap().get(par1,par2); //Thermos replacement + boolean newChunk = false; AnvilChunkLoader loader = null; @@ -209,7 +209,7 @@ - this.chunksToUnload.remove(Long.valueOf(k)); - Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(k); + this.chunksToUnload.remove(p_73158_1_, p_73158_2_); -+ Chunk chunk = this.loadedChunkHashMap_KC.rawThermos().get(p_73158_1_, p_73158_2_); //Thermos replacement ++ Chunk chunk = this.loadedChunkHashMap_KC.rawThermosMap().get(p_73158_1_, p_73158_2_); //Thermos replacement + boolean newChunk = false; // CraftBukkit if (chunk == null) @@ -293,7 +293,7 @@ - return chunk == null ? (!this.worldObj.findingSpawnPoint && !this.loadChunkOnProvideRequest ? this.defaultEmptyChunk : this.loadChunk(p_73154_1_, p_73154_2_)) : chunk; + + // CraftBukkit start -+ Chunk chunk = (Chunk) this.loadedChunkHashMap_KC.rawThermos().get(p_73154_1_, p_73154_2_); ++ Chunk chunk = (Chunk) this.loadedChunkHashMap_KC.rawThermosMap().get(p_73154_1_, p_73154_2_); + chunk = chunk == null ? (shouldLoadChunk() ? this.loadChunk(p_73154_1_, p_73154_2_) : this.defaultEmptyChunk) : chunk; // Cauldron handle forge server tick events and load the chunk within 5 seconds of the world being loaded (for chunk loaders) + + if (chunk == this.defaultEmptyChunk) @@ -527,7 +527,7 @@ - this.chunksToUnload.remove(olong); - this.loadedChunkHashMap.remove(olong.longValue()); + ForgeChunkManager.putDormantChunk(chunkcoordinates, chunk); -+ if(this.loadedChunkHashMap_KC.rawThermos().size() == 0 && ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)){ ++ if(this.loadedChunkHashMap_KC.rawThermosMap().size() == 0 && ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)){ + DimensionManager.unloadWorld(this.worldObj.provider.dimensionId); + return currentChunkProvider.unloadQueuedChunks(); + } @@ -544,7 +544,7 @@ public String makeString() { - return "ServerChunkCache: " + this.loadedChunkHashMap.getNumHashElements() + " Drop: " + this.chunksToUnload.size(); -+ return "ServerChunkCache: " + this.loadedChunkHashMap_KC.rawThermos().size() + " Drop: " + this.chunksToUnload.size(); // Cauldron ++ return "ServerChunkCache: " + this.loadedChunkHashMap_KC.rawThermosMap().size() + " Drop: " + this.chunksToUnload.size(); // Cauldron } public List getPossibleCreatures(EnumCreatureType p_73155_1_, int p_73155_2_, int p_73155_3_, int p_73155_4_) @@ -553,7 +553,7 @@ public int getLoadedChunkCount() { - return this.loadedChunkHashMap.getNumHashElements(); -+ return this.loadedChunkHashMap_KC.rawThermos().size(); // Cauldron ++ return this.loadedChunkHashMap_KC.rawThermosMap().size(); // Cauldron } public void recreateStructures(int p_82695_1_, int p_82695_2_) {} @@ -569,7 +569,7 @@ + + public long lastAccessed(int x, int z) + { -+ Chunk c = this.loadedChunkHashMap_KC.rawThermos().get(x,z); ++ Chunk c = this.loadedChunkHashMap_KC.rawThermosMap().get(x,z); + if(c == null)return 0; + else return c.lastAccessedTick; + } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 8a32e62..8662f95 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -264,7 +264,8 @@ public boolean loadChunk(int x, int z, boolean generate) { world.theChunkProviderServer.chunksToUnload.remove(x, z); //net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap_TH.get(LongHash.toLong(x, z)); - net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermos().get(x,z); //Thermos replacement for line above + //net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermos().get(x,z); //Thermos replacement for line above + net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermosMap().get(x,z); //Thermos Updated replacement for line above if (chunk == null) { world.timings.syncChunkLoadTimer.startTiming(); // Spigot diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java index de853ba..40ce7e4 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -89,7 +89,7 @@ public void run() { log.log(Level.SEVERE, " Dimension:" + world.provider.dimensionId); log.log(Level.SEVERE, - " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermos().size() + " Active Chunks: " + world.activeChunkSet.size() + " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermosMap().size() + " Active Chunks: " + world.activeChunkSet.size() + " Entities: " + world.loadedEntityList.size() + " Tile Entities: " + world.loadedTileEntityList.size()); log.log(Level.SEVERE, " Entities Last Tick: " + world.entitiesTicked); log.log(Level.SEVERE, " Tiles Last Tick: " + world.tilesTicked); @@ -153,7 +153,7 @@ else if (lastTick != 0 && System.currentTimeMillis() > lastTick + warningTime) for (net.minecraft.world.WorldServer world : MinecraftServer.getServer().worlds) { log.log(Level.WARNING, " Dimension:" + world.provider.dimensionId); - log.log(Level.WARNING, " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermos().size() + + log.log(Level.WARNING, " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.rawThermosMap().size() + " Active Chunks: " + world.activeChunkSet.size() + " Entities: " + world.loadedEntityList.size() + " Tile Entities: " + world.loadedTileEntityList.size()); diff --git a/src/main/java/thermos/wrapper/ChunkBlockHashMap.java b/src/main/java/thermos/wrapper/ChunkBlockHashMap.java index 870c4c9..d156a38 100644 --- a/src/main/java/thermos/wrapper/ChunkBlockHashMap.java +++ b/src/main/java/thermos/wrapper/ChunkBlockHashMap.java @@ -1,232 +1,198 @@ package thermos.wrapper; -import java.util.Collection; - -import com.koloboke.collect.map.LongObjMap; -import com.koloboke.collect.map.hash.HashLongObjMaps; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.world.chunk.Chunk; +import java.util.Collection; + public class ChunkBlockHashMap { - //private final ConcurrentHashMap map = new ConcurrentHashMap(); - private final LongObjMap map = HashLongObjMaps.newMutableMap(1000); - private int size = 0; - - /*public static long chunk_hash(int x, int z) - { - //return ((x & 0xFFFF) << 16) | (z & 0xFFFF); -// long key = LongHash.toLong(x, z); -// return LongHash.toLong((int) (key & 0xFFFFFFFFL), (int) (key >>> 32)); - return (((long)x)<<32L)^z; - }*/ - - /*private static int chunk_array(int index) - { - index = index % 16; - return (index + (index >> 31)) ^ (index >> 31); - } - */ - /*private Chunk[][] chunk_array_get(int x, int z) - { - Chunk[][] bunch = this.map.get(chunk_hash(x >> 4, z >> 4)); - return bunch; - }*/ - - /*private Chunk[][] chunk_array_remove(int x, int z) - { - Chunk[][] bunch = this.map.remove(chunk_hash(x >> 4, z >> 4)); - return bunch; - }*/ - - public LongObjMap raw() - { - return this.map; - } - - public int size() - { - return this.size; - } - - private Chunk last1,last2,last3,last4; - - public boolean bulkCheck(Collection coords) - { - // FYI: this class repeats a lot of code for a reason. Rather than stupidly jump around methods, - // this kind of low level, highly-optimized code requires us to avoid raising the stack size and do in-method - // optimal operations - Chunk[][] last = null; // FYI: local field does not hide a class field - int x = -1, z = -1; - for(int[] set : coords) - { - if (last != null) - { - if (set[0] >> 4 == x >> 4 && set[1] >> 4 == z >> 4) - { - x = set[0]; z = set[1]; - x %= 16; - z %= 16; - if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) - { - return false; - } - x = set[0]; z = set[1]; - } - else - { - x = set[0]; z = set[1]; - last = this.map.get((((long)(x>>4))<<32L)^(z>>4)); - if (last == null) - { - return false; - } - x %= 16; - z %= 16; - if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) - { - return false; - } - x = set[0]; z = set[1]; - - } - } - else - { - x = set[0]; z = set[1]; - last = this.map.get((((long)(x>>4))<<32L)^(z>>4)); - - if (last == null) - { - return false; - } - x %= 16; - z %= 16; - if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) - { - return false; - } - x = set[0]; z = set[1]; - } - } - - return true; - } - - public Chunk get(int x, int z) - { - if(last1 != null && last1.xPosition == x && last1.zPosition == z) - { - return last1; - } - if(last2 != null && last2.xPosition == x && last2.zPosition == z) - { - return last2; - } - if(last3 != null && last3.xPosition == x && last3.zPosition == z) - { - return last3; - } - if(last4 != null && last4.xPosition == x && last4.zPosition == z) - { - return last4; - } - - Chunk[][] bunch = this.map.get((((long)(x>>4))<<32L)^(z>>4)); - if(bunch == null) return null; - - x %= 16; - z %= 16; - Chunk ref = bunch[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)]; - - if ( ref != null) - { - last4 = last3; - last3 = last2; - last2 = last1; - last1 = ref; - } - return ref; - } - - public void put(Chunk chunk) - { - if(chunk == null) - return; - size++; - int x = chunk.xPosition, z = chunk.zPosition; - - long chunkhash = (((long)(x>>4))<<32L)^(z>>4); - - Chunk[][] temp_chunk_bunch = this.map.get(chunkhash); - - x %= 16; - z %= 16; - - x = (x + (x >> 31)) ^ (x >> 31); - z = (z + (z >> 31)) ^ (z >> 31); - - if(temp_chunk_bunch != null) - { - temp_chunk_bunch[x][z] = chunk; - } - else - { - temp_chunk_bunch = new Chunk[16][16]; - temp_chunk_bunch[x][z] = chunk; - this.map.put(chunkhash, temp_chunk_bunch); //Thermos - } - if ( chunk != null) - { - last4 = last3; - last3 = last2; - last2 = last1; - last1 = chunk; - } - } - - public void remove(Chunk chunk) - { - int x = chunk.xPosition, z = chunk.zPosition; - Chunk[][] temp_chunk_bunch = this.map.get((((long)(x>>4))<<32L)^(z>>4)); - - x %=16; - z %=16; - - x = (x + (x >> 31)) ^ (x >> 31); - z = (z + (z >> 31)) ^ (z >> 31); - - if(temp_chunk_bunch != null) - { - if(temp_chunk_bunch[x][z] != null) - { - size--; - temp_chunk_bunch[x][z] = null; - } - } - if(last1 != null && last1.xPosition == chunk.xPosition && last1.zPosition == chunk.zPosition) - { - last1 = null; - last1 = last2; - last2 = last3; - last3 = last4; - last4 = null; - } - if(last2 != null && last2.xPosition == chunk.xPosition && last2.zPosition == chunk.zPosition) - { - last2 = null; - last2 = last3; - last3 = last4; - last4 = null; - } - if(last3 != null && last3.xPosition == chunk.xPosition && last3.zPosition == chunk.zPosition) - { - last3 = null; - last3 = last4; - last4 = null; - } - if(last4 != null && last4.xPosition == chunk.xPosition && last4.zPosition == chunk.zPosition) - { - last4 = null; - } - } + /* + * ChunkBlockHashMap implementation using fastutils Long2ObjectMap + */ + + private final Long2ObjectMap map = new Long2ObjectOpenHashMap(); + private Chunk last1, last2, last3, last4; + private int size = 0; + + public Long2ObjectMap raw() { + return map; + } + + public int size() { + return size; + } + + public boolean bulkCheck(Collection coords) { + + Chunk[][] last = null; + + int x = -1, z = -1; + + for (int[] set : coords) { + + if (last != null) { + + if (set[0] >> 4 == x >> 4 && set[1] >> 4 == z >> 4) { + x = set[0]; + z = set[1]; + x %= 16; + z %= 16; + + if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) { + return false; + } + + x = set[0]; + z = set[1]; + + } else { + + x = set[0]; + z = set[1]; + + last = this.map.get((((long) (x >> 4)) << 32L) ^ (z >> 4)); + + if (last == null) { + return false; + } + + x %= 16; + z %= 16; + + if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) { + return false; + } + + x = set[0]; + z = set[1]; + + } + + } else { + x = set[0]; + z = set[1]; + + last = this.map.get((((long) (x >> 4)) << 32L) ^ (z >> 4)); + + if (last == null) { + return false; + } + + x %= 16; + z %= 16; + + if (last[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)] == null) { + return false; + } + + x = set[0]; + z = set[1]; + } + } + + return true; + } + + public Chunk get(int x, int z) { + if (last1 != null && last1.xPosition == x && last1.zPosition == z) { + return last1; + } + if (last2 != null && last2.xPosition == x && last2.zPosition == z) { + return last2; + } + if (last3 != null && last3.xPosition == x && last3.zPosition == z) { + return last3; + } + if (last4 != null && last4.xPosition == x && last4.zPosition == z) { + return last4; + } + + Chunk[][] bunch = this.map.get((((long) (x >> 4)) << 32L) ^ (z >> 4)); + if (bunch == null) return null; + + x %= 16; + z %= 16; + Chunk ref = bunch[(x + (x >> 31)) ^ (x >> 31)][(z + (z >> 31)) ^ (z >> 31)]; + + if (ref != null) { + last4 = last3; + last3 = last2; + last2 = last1; + last1 = ref; + } + return ref; + } + + public void put(Chunk chunk) { + if (chunk == null) + return; + size++; + int x = chunk.xPosition, z = chunk.zPosition; + + long chunkhash = (((long) (x >> 4)) << 32L) ^ (z >> 4); + + Chunk[][] temp_chunk_bunch = this.map.get(chunkhash); + + x %= 16; + z %= 16; + + x = (x + (x >> 31)) ^ (x >> 31); + z = (z + (z >> 31)) ^ (z >> 31); + + if (temp_chunk_bunch != null) { + temp_chunk_bunch[x][z] = chunk; + } else { + temp_chunk_bunch = new Chunk[16][16]; + temp_chunk_bunch[x][z] = chunk; + this.map.put(chunkhash, temp_chunk_bunch); //Thermos + } + if (chunk != null) { + last4 = last3; + last3 = last2; + last2 = last1; + last1 = chunk; + } + } + + public void remove(Chunk chunk) { + int x = chunk.xPosition, z = chunk.zPosition; + Chunk[][] temp_chunk_bunch = this.map.get((((long) (x >> 4)) << 32L) ^ (z >> 4)); + + x %= 16; + z %= 16; + + x = (x + (x >> 31)) ^ (x >> 31); + z = (z + (z >> 31)) ^ (z >> 31); + + if (temp_chunk_bunch != null) { + if (temp_chunk_bunch[x][z] != null) { + size--; + temp_chunk_bunch[x][z] = null; + } + } + if (last1 != null && last1.xPosition == chunk.xPosition && last1.zPosition == chunk.zPosition) { + last1 = null; + last1 = last2; + last2 = last3; + last3 = last4; + last4 = null; + } + if (last2 != null && last2.xPosition == chunk.xPosition && last2.zPosition == chunk.zPosition) { + last2 = null; + last2 = last3; + last3 = last4; + last4 = null; + } + if (last3 != null && last3.xPosition == chunk.xPosition && last3.zPosition == chunk.zPosition) { + last3 = null; + last3 = last4; + last4 = null; + } + if (last4 != null && last4.xPosition == chunk.xPosition && last4.zPosition == chunk.zPosition) { + last4 = null; + } + } + } diff --git a/src/main/java/thermos/wrapper/VanillaChunkHashMap.java b/src/main/java/thermos/wrapper/VanillaChunkHashMap.java index 9cca122..3b0d9c6 100644 --- a/src/main/java/thermos/wrapper/VanillaChunkHashMap.java +++ b/src/main/java/thermos/wrapper/VanillaChunkHashMap.java @@ -1,92 +1,102 @@ package thermos.wrapper; -import gnu.trove.map.TLongObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.util.LongHashMap; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.chunk.Chunk; - -import java.util.HashMap; -import java.util.concurrent.*; - import org.bukkit.craftbukkit.util.LongHash; +import java.util.concurrent.ConcurrentHashMap; + public class VanillaChunkHashMap extends LongHashMap { - private ChunkBlockHashMap chunkt_TH; - private ConcurrentHashMap vanilla; - public VanillaChunkHashMap(ChunkBlockHashMap chunkt_TH) { - this.chunkt_TH = chunkt_TH; - this.vanilla = new ConcurrentHashMap(); - } - + + /* + * VanillaChunkHashMap implementation using ChunkHashMap + */ + + private ChunkBlockHashMap ChunkBlockHashMap; + private Long2ObjectMap vanilla_sync; + private boolean notRealFace = false; - public VanillaChunkHashMap(ChunkBlockHashMap chunkt_TH, ConcurrentHashMap vanilla) { - this.chunkt_TH = chunkt_TH; - this.vanilla = vanilla; + + public VanillaChunkHashMap(ChunkBlockHashMap ChunkBlockHashMap) { + + this.ChunkBlockHashMap = ChunkBlockHashMap; + this.vanilla_sync = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); + + } + + public VanillaChunkHashMap(ChunkBlockHashMap ChunkBlockHashMap, ConcurrentHashMap vanilla) { + + this.ChunkBlockHashMap = ChunkBlockHashMap; + + this.vanilla_sync = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>(vanilla)); + this.notRealFace = true; + } - - public VanillaChunkHashMap thisIsNotMyRealFace() - { - return new VanillaChunkHashMap(chunkt_TH, vanilla); + + public ConcurrentHashMap convert(Long2ObjectMap map) { + return new ConcurrentHashMap(map); + } + + public VanillaChunkHashMap thisIsNotMyRealFace() { + return new VanillaChunkHashMap(ChunkBlockHashMap, convert(vanilla_sync)); } - + private long V2B(long key) { - if(notRealFace) - { + if (notRealFace) { return key; - } - else - { - return ChunkCoordIntPair.chunkXZ2Int(LongHash.msw(key) , LongHash.lsw(key)); - } - //return LongHash.toLong((int) (key & 0xFFFFFFFFL), (int) (key >>> 32)); + } else { + return ChunkCoordIntPair.chunkXZ2Int(LongHash.msw(key), LongHash.lsw(key)); + } } - - public ConcurrentHashMap rawVanilla() - { - return vanilla; + + public ConcurrentHashMap rawVanilla() { + return convert(vanilla_sync); } - - public ChunkBlockHashMap rawThermos() - { - return chunkt_TH; + + public ChunkBlockHashMap rawThermosMap() { + return ChunkBlockHashMap; } - - public int size() - { - return this.chunkt_TH.size(); + + public int size() { + return this.ChunkBlockHashMap.size(); } - + @Override public void add(long key, Object value) { - if(value instanceof Chunk) - { - Chunk c = (Chunk) value; - chunkt_TH.put(c); - vanilla.put(V2B(key), c); - } + if (value instanceof Chunk) { + + Chunk c = (Chunk) value; + + ChunkBlockHashMap.put(c); + vanilla_sync.put(V2B(key), c); + } } - + @Override public boolean containsItem(long key) { - return vanilla.containsKey(V2B(key)); + return vanilla_sync.containsKey(V2B(key)); } - + @Override public Object getValueByKey(long key) { - return vanilla.get(V2B(key)); + return vanilla_sync.get(V2B(key)); } - + @Override public Object remove(long key) { - Object o = vanilla.remove(V2B(key)); - if(o instanceof Chunk) // Thermos - Use our special map + Object o = vanilla_sync.remove(V2B(key)); + if (o instanceof Chunk) // Thermos - Use our special map { - Chunk c = (Chunk)o; - chunkt_TH.remove(c); + Chunk c = (Chunk) o; + ChunkBlockHashMap.remove(c); } return o; } - -} + +} \ No newline at end of file