CavePVP-Stuff/cSpigot-master/spigot-server-Patches/0184-Reimplement-FlatMap.patch

364 lines
14 KiB
Diff
Raw Normal View History

2023-05-01 20:59:40 +02:00
From 8dd291089bfd73acfc3a170e496bf34e855b1de1 Mon Sep 17 00:00:00 2001
From: Alfie Cleveland <alfeh@me.com>
Date: Sun, 9 Jul 2017 00:41:19 +0100
Subject: [PATCH] Reimplement FlatMap
diff --git a/src/main/java/net/frozenorb/util/ChunkFlatMap.java b/src/main/java/net/frozenorb/util/ChunkFlatMap.java
new file mode 100644
index 000000000..6d937ec68
--- /dev/null
+++ b/src/main/java/net/frozenorb/util/ChunkFlatMap.java
@@ -0,0 +1,28 @@
+package net.frozenorb.util;
+
+import net.minecraft.server.Chunk;
+
+public class ChunkFlatMap extends FlatMap<Chunk> {
+
+ private Chunk lastChunk;
+
+ @Override
+ public Chunk get(int x, int z) {
+ Chunk last = lastChunk; // have to do this to be somewhat thread-safe-ish
+
+ if (last != null && last.locX == x && last.locZ == z) {
+ return last;
+ }
+
+ return lastChunk = super.get(x, z);
+ }
+
+ @Override
+ public void remove(int x, int z) {
+ if (lastChunk != null && lastChunk.locX == x && lastChunk.locZ == z) {
+ lastChunk = null; // we don't really care for thread safety here, we'd just lose a few cache hits
+ }
+
+ super.remove(x, z);
+ }
+}
diff --git a/src/main/java/net/frozenorb/util/CoordinateChunkHybridMap.java b/src/main/java/net/frozenorb/util/CoordinateChunkHybridMap.java
new file mode 100644
index 000000000..bd912d30b
--- /dev/null
+++ b/src/main/java/net/frozenorb/util/CoordinateChunkHybridMap.java
@@ -0,0 +1,10 @@
+package net.frozenorb.util;
+
+import net.minecraft.server.Chunk;
+
+public class CoordinateChunkHybridMap extends CoordinateObjectHybridMap<Chunk> {
+
+ public CoordinateChunkHybridMap() {
+ flatMap = new ChunkFlatMap();
+ }
+}
diff --git a/src/main/java/net/frozenorb/util/CoordinateObjectHybridMap.java b/src/main/java/net/frozenorb/util/CoordinateObjectHybridMap.java
new file mode 100644
index 000000000..ac015051c
--- /dev/null
+++ b/src/main/java/net/frozenorb/util/CoordinateObjectHybridMap.java
@@ -0,0 +1,56 @@
+package net.frozenorb.util;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.bukkit.craftbukkit.util.LongHash;
+
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+
+public class CoordinateObjectHybridMap<T> {
+
+ private Long2ObjectOpenHashMap<T> backingMap = new Long2ObjectOpenHashMap<T>();
+ private Collection<T> values = Collections.unmodifiableCollection(backingMap.values()); // values() is uncached and is simply a view, so we can cache it and make it externally unmodifiable
+
+ protected FlatMap<T> flatMap;
+
+ public CoordinateObjectHybridMap() {
+ this.flatMap = new FlatMap<T>();
+ }
+
+ public boolean contains(int x, int z) {
+ return get(x, z) != null;
+ }
+
+ public T get(int x, int z) {
+ if (x * x < FlatMap.HALF_DIAMETER_SQUARED && z * z < FlatMap.HALF_DIAMETER_SQUARED) {
+ return flatMap.get(x, z);
+ }
+
+ return backingMap.get(LongHash.toLong(x, z));
+ }
+
+ public void remove(int x, int z) {
+ if (x * x < FlatMap.HALF_DIAMETER_SQUARED && z * z < FlatMap.HALF_DIAMETER_SQUARED) {
+ flatMap.put(x, z, null);
+ }
+
+ backingMap.remove(LongHash.toLong(x, z));
+ }
+
+ public void put(int x, int z, T value) {
+ if (x * x < FlatMap.HALF_DIAMETER_SQUARED && z * z < FlatMap.HALF_DIAMETER_SQUARED) {
+ flatMap.put(x, z, value);
+ }
+
+ backingMap.put(LongHash.toLong(x, z), value);
+ }
+
+ public int size() {
+ return backingMap.size();
+ }
+
+ public Collection<T> values() {
+ return values;
+ }
+}
diff --git a/src/main/java/net/frozenorb/util/FlatMap.java b/src/main/java/net/frozenorb/util/FlatMap.java
new file mode 100644
index 000000000..6a5c36fa2
--- /dev/null
+++ b/src/main/java/net/frozenorb/util/FlatMap.java
@@ -0,0 +1,30 @@
+package net.frozenorb.util;
+
+public class FlatMap<V> {
+
+ private static final int DIAMETER = 4096;
+ private static final int HALF_DIAMETER = DIAMETER / 2;
+ private final Object[] flatLookup;
+
+ public static final int HALF_DIAMETER_SQUARED = HALF_DIAMETER * HALF_DIAMETER;
+
+ public FlatMap() {
+ this.flatLookup = new Object[DIAMETER * DIAMETER];
+ }
+
+ public void put(final int msw, final int lsw, final V value) {
+ this.flatLookup[(msw + HALF_DIAMETER) * DIAMETER + (lsw + HALF_DIAMETER)] = value;
+ }
+
+ public void remove(final int msw, final int lsw) {
+ this.put(msw, lsw, null);
+ }
+
+ public boolean contains(final int msw, final int lsw) {
+ return this.get(msw, lsw) != null;
+ }
+
+ public V get(final int msw, final int lsw) {
+ return (V) this.flatLookup[(msw + HALF_DIAMETER) * DIAMETER + (lsw + HALF_DIAMETER)];
+ }
+}
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index b4ddc3bbf..5a061b274 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1,28 +1,22 @@
package net.minecraft.server;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import net.minecraft.util.com.google.common.collect.Lists;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
// CraftBukkit start
import java.util.Random;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.bukkit.Server;
import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
import org.bukkit.craftbukkit.util.LongHash;
import org.bukkit.craftbukkit.util.LongHashSet;
-import org.bukkit.craftbukkit.util.LongObjectHashMap;
import org.bukkit.event.world.ChunkUnloadEvent;
// CraftBukkit end
+import net.frozenorb.util.CoordinateChunkHybridMap;
+import net.frozenorb.util.CoordinateObjectHybridMap;
+
public class ChunkProviderServer implements IChunkProvider {
private static final Logger b = LogManager.getLogger();
@@ -32,7 +26,8 @@ public class ChunkProviderServer implements IChunkProvider {
public IChunkProvider chunkProvider;
private IChunkLoader f;
public boolean forceChunkLoad = false; // true -> false
- public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>();
+ //public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>();
+ public CoordinateObjectHybridMap<Chunk> chunks = new CoordinateChunkHybridMap(); // MineHQ
public WorldServer world;
// CraftBukkit end
@@ -44,7 +39,7 @@ public class ChunkProviderServer implements IChunkProvider {
}
public boolean isChunkLoaded(int i, int j) {
- return this.chunks.containsKey(LongHash.toLong(i, j)); // CraftBukkit
+ return this.chunks.contains(i, j); // CraftBukkit // MineHQ
}
// CraftBukkit start - Change return type to Collection and return the values of our chunk map
@@ -56,7 +51,7 @@ public class ChunkProviderServer implements IChunkProvider {
public void queueUnload(int i, int j) {
// PaperSpigot start - Asynchronous lighting updates
- Chunk chunk = this.chunks.get(LongHash.toLong(i, j));
+ Chunk chunk = this.chunks.get(i, j); // MineHQ
if (chunk != null && chunk.world.paperSpigotConfig.useAsyncLighting && (chunk.pendingLightUpdates.get() > 0 || chunk.world.getTime() - chunk.lightUpdateTime < 20)) {
return;
}
@@ -82,20 +77,22 @@ public class ChunkProviderServer implements IChunkProvider {
if (k < -short1 || k > short1 || l < -short1 || l > short1 || !(this.world.keepSpawnInMemory)) { // Added 'this.world.keepSpawnInMemory'
this.unloadQueue.add(i, j);
- Chunk c = this.chunks.get(LongHash.toLong(i, j));
- if (c != null) {
- c.mustSave = true;
+ // MineHQ start - don't lookup twice
+ if (chunk != null) {
+ chunk.mustSave = true;
}
+ // MineHQ end
}
// CraftBukkit end
} else {
// CraftBukkit start
this.unloadQueue.add(i, j);
- Chunk c = this.chunks.get(LongHash.toLong(i, j));
- if (c != null) {
- c.mustSave = true;
+ // MineHQ start - don't lookup twice
+ if (chunk != null) {
+ chunk.mustSave = true;
}
+ // MineHQ end
// CraftBukkit end
}
}
@@ -112,7 +109,7 @@ public class ChunkProviderServer implements IChunkProvider {
// CraftBukkit start - Add async variant, provide compatibility
public Chunk getChunkIfLoaded(int x, int z) {
- return this.chunks.get(LongHash.toLong(x, z));
+ return this.chunks.get(x, z); // MineHQ
}
public Chunk getChunkAt(int i, int j) {
@@ -121,7 +118,7 @@ public class ChunkProviderServer implements IChunkProvider {
public Chunk getChunkAt(int i, int j, Runnable runnable) {
this.unloadQueue.remove(i, j);
- Chunk chunk = this.chunks.get(LongHash.toLong(i, j));
+ Chunk chunk = this.chunks.get(i, j); // MineHQ
ChunkRegionLoader loader = null;
if (this.f instanceof ChunkRegionLoader) {
@@ -150,7 +147,7 @@ public class ChunkProviderServer implements IChunkProvider {
public Chunk originalGetChunkAt(int i, int j) {
this.unloadQueue.remove(i, j);
- Chunk chunk = (Chunk) this.chunks.get(LongHash.toLong(i, j));
+ Chunk chunk = (Chunk) this.chunks.get(i, j); // MineHQ
boolean newChunk = false;
if (chunk == null) {
@@ -175,7 +172,7 @@ public class ChunkProviderServer implements IChunkProvider {
newChunk = true; // CraftBukkit
}
- this.chunks.put(LongHash.toLong(i, j), chunk); // CraftBukkit
+ this.chunks.put(i, j, chunk); // CraftBukkit // MineHQ
chunk.addEntities();
// CraftBukkit start
@@ -213,7 +210,7 @@ public class ChunkProviderServer implements IChunkProvider {
public Chunk getOrCreateChunk(int i, int j) {
// CraftBukkit start
- Chunk chunk = (Chunk) this.chunks.get(LongHash.toLong(i, j));
+ Chunk chunk = (Chunk) this.chunks.get(i, j); // MineHQ
chunk = chunk == null ? (!this.world.isLoading && !this.forceChunkLoad ? this.emptyChunk : this.getChunkAt(i, j)) : chunk;
if (chunk == this.emptyChunk) return chunk;
@@ -360,7 +357,11 @@ public class ChunkProviderServer implements IChunkProvider {
Server server = this.world.getServer();
for (int i = 0; i < 100 && !this.unloadQueue.isEmpty(); i++) {
long chunkcoordinates = this.unloadQueue.popFirst();
- Chunk chunk = this.chunks.get(chunkcoordinates);
+ // MineHQ start
+ int locX = LongHash.msw(chunkcoordinates);
+ int locZ = LongHash.lsw(chunkcoordinates);
+ Chunk chunk = this.chunks.get(locX, locZ);
+ // MineHQ end
if (chunk == null) continue;
ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk);
@@ -370,7 +371,7 @@ public class ChunkProviderServer implements IChunkProvider {
chunk.removeEntities();
this.saveChunk(chunk);
this.saveChunkNOP(chunk);
- this.chunks.remove(chunkcoordinates); // CraftBukkit
+ this.chunks.remove(locX, locZ); // CraftBukkit // MineHQ
}
// this.unloadQueue.remove(olong);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 8f4a96fe6..7e5ae9e4e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -232,7 +232,7 @@ public class CraftWorld implements World {
}
world.chunkProviderServer.unloadQueue.remove(x, z);
- world.chunkProviderServer.chunks.remove(LongHash.toLong(x, z));
+ world.chunkProviderServer.chunks.remove(x, z); // MineHQ
return true;
}
@@ -290,7 +290,7 @@ public class CraftWorld implements World {
}
world.chunkProviderServer.unloadQueue.remove(x, z);
- net.minecraft.server.Chunk chunk = world.chunkProviderServer.chunks.get(LongHash.toLong(x, z));
+ net.minecraft.server.Chunk chunk = world.chunkProviderServer.chunks.get(x, z); // MineHQ
if (chunk == null) {
world.timings.syncChunkLoadTimer.startTiming(); // Spigot
@@ -304,7 +304,7 @@ public class CraftWorld implements World {
private void chunkLoadPostProcess(net.minecraft.server.Chunk chunk, int x, int z) {
if (chunk != null) {
- world.chunkProviderServer.chunks.put(LongHash.toLong(x, z), chunk);
+ world.chunkProviderServer.chunks.put(x, z, chunk); // MineHQ
chunk.addEntities();
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
index c249e776d..8c6f2a221 100644
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
@@ -36,7 +36,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
queuedChunk.loader.loadEntities(chunk, queuedChunk.compound.getCompound("Level"), queuedChunk.world);
chunk.lastSaved = queuedChunk.provider.world.getTime();
- queuedChunk.provider.chunks.put(LongHash.toLong(queuedChunk.x, queuedChunk.z), chunk);
+ queuedChunk.provider.chunks.put(queuedChunk.x, queuedChunk.z, chunk); // MineHQ
chunk.addEntities();
if (queuedChunk.provider.chunkProvider != null) {
--
2.13.3