9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-23 17:09:29 +00:00
Files
Leaf/patches/server/0047-Hearse-Complete-half-of-the-code-and-fix-some-proble.patch
2023-01-13 00:15:47 -05:00

1765 lines
84 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Mon, 9 Jan 2023 12:35:11 +0800
Subject: [PATCH] Hearse: Complete half of the code and fix some problems
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java b/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
index 2a43625d13d7aa253c15aba8092ac9361785a5f0..52f0c9dddf29a28cc360fbacb923445e5c3f82a6 100644
--- a/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
+++ b/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
@@ -4,12 +4,19 @@ import io.papermc.paper.util.TickThread;
public class WorkerThread extends TickThread {
+
public WorkerThread(String name) {
super(name);
this.setDaemon(true);
this.setPriority(Thread.NORM_PRIORITY - 2);
}
+ public WorkerThread(Runnable run, String name) {
+ super(run, name);
+ this.setDaemon(true);
+ this.setPriority(Thread.NORM_PRIORITY - 2);
+ }
+
public static boolean isWorker(){
return Thread.currentThread() instanceof WorkerThread;
}
diff --git a/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
index f7ca6d650d9089b65137d61acca64c89e5b4db22..8899c02a2242b51097a03c7e3ca03b8768c60117 100644
--- a/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
+++ b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
@@ -10,11 +10,11 @@ public class WorkerThreadPoolExecutor extends ThreadPoolExecutor {
private final Queue<TaskEntry> taskEntries = new ConcurrentLinkedQueue<>();
public WorkerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull WorkerThreadFactory workerThreadFactory) {
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,r->workerThreadFactory.getNewThread(r));
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, workerThreadFactory::getNewThread);
}
public WorkerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull WorkerThreadFactory workerThreadFactory, @NotNull RejectedExecutionHandler handler) {
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,r->workerThreadFactory.getNewThread(r), handler);
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, workerThreadFactory::getNewThread, handler);
}
public void executeWithSubTask(Runnable mainTask,Runnable subTask){
diff --git a/src/main/java/co/earthme/hearse/server/ServerHook.java b/src/main/java/co/earthme/hearse/server/ServerHook.java
index 22260735664d986fed6bf82e4016b647417e1932..524a55c3298a079e416c742641af55725a602a2b 100644
--- a/src/main/java/co/earthme/hearse/server/ServerHook.java
+++ b/src/main/java/co/earthme/hearse/server/ServerHook.java
@@ -5,6 +5,8 @@ import co.earthme.hearse.concurrent.WorkerThreadPoolExecutor;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
+import org.apache.logging.log4j.LogManager;
+
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -19,7 +21,7 @@ public class ServerHook {
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
task -> {
- WorkerThread workerThread = new WorkerThread("Hearse-Worker-Thread # "+threadId.getAndIncrement());
+ WorkerThread workerThread = new WorkerThread(task,"Hearse-Worker-Thread # "+threadId.getAndIncrement());
return workerThread;
}
);
diff --git a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java
index f72d99bea1c78c8882793fa8ee3dc3642be1b8c7..62a74cbdb7f04b652dddac9e9c6191d5b86c3323 100644
--- a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java
+++ b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java
@@ -37,11 +37,11 @@ public final class PlayerChunkLoader {
public static final int LOADED_TICKET_LEVEL = 33;
public static int getTickViewDistance(final Player player) {
- return getTickViewDistance(((CraftPlayer)player).getHandle());
+ return getTickViewDistance(((CraftPlayer) player).getHandle());
}
public static int getTickViewDistance(final ServerPlayer player) {
- final ServerLevel level = (ServerLevel)player.level;
+ final ServerLevel level = (ServerLevel) player.level;
final PlayerLoaderData data = level.chunkSource.chunkMap.playerChunkManager.getData(player);
if (data == null) {
return level.chunkSource.chunkMap.playerChunkManager.getTargetTickViewDistance();
@@ -50,11 +50,11 @@ public final class PlayerChunkLoader {
}
public static int getLoadViewDistance(final Player player) {
- return getLoadViewDistance(((CraftPlayer)player).getHandle());
+ return getLoadViewDistance(((CraftPlayer) player).getHandle());
}
public static int getLoadViewDistance(final ServerPlayer player) {
- final ServerLevel level = (ServerLevel)player.level;
+ final ServerLevel level = (ServerLevel) player.level;
final PlayerLoaderData data = level.chunkSource.chunkMap.playerChunkManager.getData(player);
if (data == null) {
return level.chunkSource.chunkMap.playerChunkManager.getLoadDistance();
@@ -63,11 +63,11 @@ public final class PlayerChunkLoader {
}
public static int getSendViewDistance(final Player player) {
- return getSendViewDistance(((CraftPlayer)player).getHandle());
+ return getSendViewDistance(((CraftPlayer) player).getHandle());
}
public static int getSendViewDistance(final ServerPlayer player) {
- final ServerLevel level = (ServerLevel)player.level;
+ final ServerLevel level = (ServerLevel) player.level;
final PlayerLoaderData data = level.chunkSource.chunkMap.playerChunkManager.getData(player);
if (data == null) {
return level.chunkSource.chunkMap.playerChunkManager.getTargetSendDistance();
@@ -75,9 +75,6 @@ public final class PlayerChunkLoader {
return data.getTargetSendViewDistance();
}
- private final StampedLock sendLock = new StampedLock();
- private final StampedLock loadLock = new StampedLock();
-
protected final ChunkMap chunkMap;
protected final Reference2ObjectLinkedOpenHashMap<ServerPlayer, PlayerLoaderData> playerMap = new Reference2ObjectLinkedOpenHashMap<>(512, 0.7f);
protected final ReferenceLinkedOpenHashSet<PlayerLoaderData> chunkSendQueue = new ReferenceLinkedOpenHashSet<>(512, 0.7f);
@@ -376,7 +373,7 @@ public final class PlayerChunkLoader {
}
return !(data.hasSentChunk(chunkX - 1, chunkZ) && data.hasSentChunk(chunkX + 1, chunkZ) &&
- data.hasSentChunk(chunkX, chunkZ - 1) && data.hasSentChunk(chunkX, chunkZ + 1));
+ data.hasSentChunk(chunkX, chunkZ - 1) && data.hasSentChunk(chunkX, chunkZ + 1));
}
protected int getMaxConcurrentChunkSends() {
@@ -386,15 +383,15 @@ public final class PlayerChunkLoader {
protected int getMaxChunkLoads() {
double config = GlobalConfiguration.get().chunkLoading.playerMaxConcurrentLoads;
double max = GlobalConfiguration.get().chunkLoading.globalMaxConcurrentLoads;
- return (int)Math.ceil(Math.min(config * MinecraftServer.getServer().getPlayerCount(), max <= 1.0 ? Double.MAX_VALUE : max));
+ return (int) Math.ceil(Math.min(config * MinecraftServer.getServer().getPlayerCount(), max <= 1.0 ? Double.MAX_VALUE : max));
}
protected long getTargetSendPerPlayerAddend() {
- return GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate <= 1.0 ? 0L : (long)Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate);
+ return GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate <= 1.0 ? 0L : (long) Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.targetPlayerChunkSendRate);
}
protected long getMaxSendAddend() {
- return GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate <= 1.0 ? 0L : (long)Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate);
+ return GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate <= 1.0 ? 0L : (long) Math.round(1.0e9 / GlobalConfiguration.get().chunkLoading.globalMaxChunkSendRate);
}
public void onChunkPlayerTickReady(final int chunkX, final int chunkZ) {
@@ -416,7 +413,7 @@ public final class PlayerChunkLoader {
if (!(raw instanceof ServerPlayer)) {
continue;
}
- this.onChunkSendReady((ServerPlayer)raw, chunkX, chunkZ);
+ this.onChunkSendReady((ServerPlayer) raw, chunkX, chunkZ);
}
}
@@ -485,19 +482,9 @@ public final class PlayerChunkLoader {
}
loaderData.remove();
- long id1 = this.loadLock.writeLock();
- try {
- this.chunkLoadQueue.remove(loaderData);
- }finally {
- this.loadLock.unlockWrite(id1);
- }
+ this.chunkLoadQueue.remove(loaderData);
- final long id = this.sendLock.writeLock();
- try {
- this.chunkSendQueue.remove(loaderData);
- }finally {
- this.sendLock.unlockWrite(id);
- }
+ this.chunkSendQueue.remove(loaderData);
this.chunkSendWaitQueue.remove(loaderData);
synchronized (this.sendingChunkCounts) {
@@ -534,49 +521,34 @@ public final class PlayerChunkLoader {
protected static final AtomicInteger concurrentChunkSends = new AtomicInteger();
protected final Reference2IntOpenHashMap<PlayerLoaderData> sendingChunkCounts = new Reference2IntOpenHashMap<>();
private static long nextChunkSend;
+
private void trySendChunks() {
final long time = System.nanoTime();
if (time < nextChunkSend) {
return;
}
- final long id = this.sendLock.writeLock();
- try {
- // drain entries from wait queue
- while (!this.chunkSendWaitQueue.isEmpty()) {
- final PlayerLoaderData data = this.chunkSendWaitQueue.first();
+ // drain entries from wait queue
+ while (!this.chunkSendWaitQueue.isEmpty()) {
+ final PlayerLoaderData data = this.chunkSendWaitQueue.first();
- if (data.nextChunkSendTarget > time) {
- break;
- }
+ if (data.nextChunkSendTarget > time) {
+ break;
+ }
- this.chunkSendWaitQueue.pollFirst();
+ this.chunkSendWaitQueue.pollFirst();
- this.chunkSendQueue.add(data);
- }
- }finally {
- this.sendLock.unlockWrite(id);
+ this.chunkSendQueue.add(data);
}
- long id2 = this.sendLock.readLock();
- try {
- if (this.chunkSendQueue.isEmpty()) {
- return;
- }
- }finally {
- this.sendLock.unlockRead(id2);
+ if (this.chunkSendQueue.isEmpty()) {
+ return;
}
final int maxSends = this.getMaxConcurrentChunkSends();
final long nextPlayerDeadline = this.getTargetSendPerPlayerAddend() + time;
- for (;;) {
-
- long id3 = this.sendLock.readLock();
- try {
- if (this.chunkSendQueue.isEmpty()) {
- break;
- }
- }finally {
- this.sendLock.unlockRead(id3);
+ for (; ; ) {
+ if (this.chunkSendQueue.isEmpty()) {
+ break;
}
final int currSends = concurrentChunkSends.get();
@@ -590,29 +562,17 @@ public final class PlayerChunkLoader {
// send chunk
- PlayerLoaderData data;
-
- final long id4 = this.sendLock.writeLock();
- try {
- data = this.chunkSendQueue.removeFirst();
- }finally {
- this.sendLock.unlockWrite(id4);
- }
+ PlayerLoaderData data = this.chunkSendQueue.removeFirst();
final ChunkPriorityHolder queuedSend = data.sendQueue.pollFirst();
if (queuedSend == null) {
concurrentChunkSends.getAndDecrement(); // we never sent, so decrease
// stop iterating over players who have nothing to send
- final long id5 = this.sendLock.readLock();
- try {
- if (this.chunkSendQueue.isEmpty()) {
- // nothing left
- break;
- }
- continue;
- }finally {
- this.sendLock.unlockRead(id5);
+ if (this.chunkSendQueue.isEmpty()) {
+ // nothing left
+ break;
}
+ continue;
}
if (!this.isChunkPlayerLoaded(queuedSend.chunkX, queuedSend.chunkZ)) {
@@ -620,7 +580,6 @@ public final class PlayerChunkLoader {
}
data.nextChunkSendTarget = nextPlayerDeadline;
- this.sendLock.writeLock();
synchronized (this.sendingChunkCounts) {
this.sendingChunkCounts.addTo(data, 1);
@@ -652,43 +611,27 @@ public final class PlayerChunkLoader {
protected int concurrentChunkLoads;
// this interval prevents bursting a lot of chunk loads
- protected static final IntervalledCounter TICKET_ADDITION_COUNTER_SHORT = new IntervalledCounter((long)(1.0e6 * 50.0)); // 50ms
+ protected static final IntervalledCounter TICKET_ADDITION_COUNTER_SHORT = new IntervalledCounter((long) (1.0e6 * 50.0)); // 50ms
// this interval ensures the rate is kept between ticks correctly
- protected static final IntervalledCounter TICKET_ADDITION_COUNTER_LONG = new IntervalledCounter((long)(1.0e6 * 1000.0)); // 1000ms
+ protected static final IntervalledCounter TICKET_ADDITION_COUNTER_LONG = new IntervalledCounter((long) (1.0e6 * 1000.0)); // 1000ms
+
private void tryLoadChunks() {
- final long id = this.loadLock.writeLock();
- try {
- if (this.chunkLoadQueue.isEmpty()) {
- return;
- }
- }finally {
- this.loadLock.unlockWrite(id);
+ if (this.chunkLoadQueue.isEmpty()) {
+ return;
}
final int maxLoads = this.getMaxChunkLoads();
final long time = System.nanoTime();
boolean updatedCounters = false;
- for (;;) {
- PlayerLoaderData data;
-
- final long id1 = this.loadLock.writeLock();
- try {
- data = this.chunkLoadQueue.pollFirst();
- }finally {
- this.loadLock.unlock(id1);
- }
+ for (; ; ) {
+ PlayerLoaderData data = this.chunkLoadQueue.pollFirst();
data.lastChunkLoad = time;
final ChunkPriorityHolder queuedLoad = data.loadQueue.peekFirst();
if (queuedLoad == null) {
- long id2 = this.loadLock.writeLock();
- try {
- if (this.chunkLoadQueue.isEmpty()) {
- break;
- }
- }finally {
- this.loadLock.unlockWrite(id2);
+ if (this.chunkLoadQueue.isEmpty()) {
+ break;
}
continue;
}
@@ -704,12 +647,7 @@ public final class PlayerChunkLoader {
if (this.isChunkPlayerLoaded(queuedLoad.chunkX, queuedLoad.chunkZ)) {
// already loaded!
data.loadQueue.pollFirst(); // already loaded so we just skip
- final long id3 = this.loadLock.writeLock();
- try {
- this.chunkLoadQueue.add(data);
- }finally {
- this.loadLock.unlockWrite(id3);
- }
+ this.chunkLoadQueue.add(data);
// ensure the chunk is queued to send
this.onChunkSendReady(queuedLoad.chunkX, queuedLoad.chunkZ);
continue;
@@ -739,14 +677,9 @@ public final class PlayerChunkLoader {
final int currentChunkLoads = this.concurrentChunkLoads;
if (currentChunkLoads >= maxLoads || (GlobalConfiguration.get().chunkLoading.globalMaxChunkLoadRate > 0 && (TICKET_ADDITION_COUNTER_SHORT.getRate() >= GlobalConfiguration.get().chunkLoading.globalMaxChunkLoadRate || TICKET_ADDITION_COUNTER_LONG.getRate() >= GlobalConfiguration.get().chunkLoading.globalMaxChunkLoadRate))
- || (GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate > 0.0 && (data.ticketAdditionCounterShort.getRate() >= GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate || data.ticketAdditionCounterLong.getRate() >= GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate))) {
+ || (GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate > 0.0 && (data.ticketAdditionCounterShort.getRate() >= GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate || data.ticketAdditionCounterLong.getRate() >= GlobalConfiguration.get().chunkLoading.playerMaxChunkLoadRate))) {
// don't poll, we didn't load it
- final long id4 = this.loadLock.writeLock();
- try {
- this.chunkLoadQueue.add(data);
- }finally {
- this.loadLock.unlockWrite(id4);
- }
+ this.chunkLoadQueue.add(data);
break;
}
}
@@ -755,12 +688,7 @@ public final class PlayerChunkLoader {
data.loadQueue.pollFirst();
// now that we've polled we can re-add to load queue
- final long id4 = this.loadLock.writeLock();
- try {
- this.chunkLoadQueue.add(data);
- }finally {
- this.loadLock.unlockWrite(id4);
- }
+ this.chunkLoadQueue.add(data);
// add necessary tickets to load chunk up to send-ready
for (int dz = -1; dz <= 1; ++dz) {
@@ -840,7 +768,7 @@ public final class PlayerChunkLoader {
protected static final double PRIORITISED_DISTANCE = 12.0 * 16.0;
// Player max sprint speed is approximately 8m/s
- protected static final double LOOK_PRIORITY_SPEED_THRESHOLD = (10.0/20.0) * (10.0/20.0);
+ protected static final double LOOK_PRIORITY_SPEED_THRESHOLD = (10.0 / 20.0) * (10.0 / 20.0);
protected static final double LOOK_PRIORITY_YAW_DELTA_RECALC_THRESHOLD = 3.0f;
protected double lastLocX = Double.NEGATIVE_INFINITY;
@@ -887,9 +815,9 @@ public final class PlayerChunkLoader {
protected long nextChunkSendTarget;
// this interval prevents bursting a lot of chunk loads
- protected final IntervalledCounter ticketAdditionCounterShort = new IntervalledCounter((long)(1.0e6 * 50.0)); // 50ms
+ protected final IntervalledCounter ticketAdditionCounterShort = new IntervalledCounter((long) (1.0e6 * 50.0)); // 50ms
// this ensures the rate is kept between ticks correctly
- protected final IntervalledCounter ticketAdditionCounterLong = new IntervalledCounter((long)(1.0e6 * 1000.0)); // 1000ms
+ protected final IntervalledCounter ticketAdditionCounterLong = new IntervalledCounter((long) (1.0e6 * 1000.0)); // 1000ms
public long lastChunkLoad;
@@ -986,14 +914,14 @@ public final class PlayerChunkLoader {
// b = ((p3z - p1z)(targetX - p3x) + (p1x - p3x)(targetZ - p3z)) / d
// c = 1.0 - a - b
- final double d = (p2z - p3z)*(p1x - p3x) + (p3x - p2x)*(p1z - p3z);
- final double a = ((p2z - p3z)*(targetX - p3x) + (p3x - p2x)*(targetZ - p3z)) / d;
+ final double d = (p2z - p3z) * (p1x - p3x) + (p3x - p2x) * (p1z - p3z);
+ final double a = ((p2z - p3z) * (targetX - p3x) + (p3x - p2x) * (targetZ - p3z)) / d;
if (a < 0.0 || a > 1.0) {
return false;
}
- final double b = ((p3z - p1z)*(targetX - p3x) + (p1x - p3x)*(targetZ - p3z)) / d;
+ final double b = ((p3z - p1z) * (targetX - p3x) + (p1x - p3x) * (targetZ - p3z)) / d;
if (b < 0.0 || b > 1.0) {
return false;
}
@@ -1040,14 +968,14 @@ public final class PlayerChunkLoader {
&& tickViewDistance == this.lastTickDistance
&& (this.usingLookingPriority ? (
- // has our block stayed the same (this also accounts for chunk change)?
- Mth.floor(this.lastLocX) == Mth.floor(posX)
+ // has our block stayed the same (this also accounts for chunk change)?
+ Mth.floor(this.lastLocX) == Mth.floor(posX)
&& Mth.floor(this.lastLocZ) == Mth.floor(posZ)
- ) : (
- // has our chunk stayed the same
- (Mth.floor(this.lastLocX) >> 4) == (Mth.floor(posX) >> 4)
+ ) : (
+ // has our chunk stayed the same
+ (Mth.floor(this.lastLocX) >> 4) == (Mth.floor(posX) >> 4)
&& (Mth.floor(this.lastLocZ) >> 4) == (Mth.floor(posZ) >> 4)
- ))
+ ))
// has our decision about look priority changed?
&& this.usingLookingPriority == useLookPriority
@@ -1096,15 +1024,15 @@ public final class PlayerChunkLoader {
final double p1z = posZ;
// to the left of the looking direction
- final double p2x = PRIORITISED_DISTANCE * Math.cos(Math.toRadians(yaw + (double)(FOV / 2.0))) // calculate rotated vector
+ final double p2x = PRIORITISED_DISTANCE * Math.cos(Math.toRadians(yaw + (double) (FOV / 2.0))) // calculate rotated vector
+ p1x; // offset vector
- final double p2z = PRIORITISED_DISTANCE * Math.sin(Math.toRadians(yaw + (double)(FOV / 2.0))) // calculate rotated vector
+ final double p2z = PRIORITISED_DISTANCE * Math.sin(Math.toRadians(yaw + (double) (FOV / 2.0))) // calculate rotated vector
+ p1z; // offset vector
// to the right of the looking direction
- final double p3x = PRIORITISED_DISTANCE * Math.cos(Math.toRadians(yaw - (double)(FOV / 2.0))) // calculate rotated vector
+ final double p3x = PRIORITISED_DISTANCE * Math.cos(Math.toRadians(yaw - (double) (FOV / 2.0))) // calculate rotated vector
+ p1x; // offset vector
- final double p3z = PRIORITISED_DISTANCE * Math.sin(Math.toRadians(yaw - (double)(FOV / 2.0))) // calculate rotated vector
+ final double p3z = PRIORITISED_DISTANCE * Math.sin(Math.toRadians(yaw - (double) (FOV / 2.0))) // calculate rotated vector
+ p1z; // offset vector
// now that we have all of our points, we can recalculate the load queue
@@ -1142,7 +1070,7 @@ public final class PlayerChunkLoader {
p1x, p1z, p2x, p2z, p3x, p3z,
// center of chunk
- (double)((chunkX << 4) | 8), (double)((chunkZ << 4) | 8)
+ (double) ((chunkX << 4) | 8), (double) ((chunkZ << 4) | 8)
);
final int manhattanDistance = Math.abs(dx) + Math.abs(dz);
@@ -1157,9 +1085,9 @@ public final class PlayerChunkLoader {
if (prioritised) {
// we don't prioritise these chunks above others because we also want to make sure some chunks
// will be loaded if the player changes direction
- priority = (double)manhattanDistance / 6.0;
+ priority = (double) manhattanDistance / 6.0;
} else {
- priority = (double)manhattanDistance;
+ priority = (double) manhattanDistance;
}
}
@@ -1186,23 +1114,13 @@ public final class PlayerChunkLoader {
});
// we're modifying loadQueue, must remove
- final long id3 = this.loader.loadLock.writeLock();
- try {
- this.loader.chunkLoadQueue.remove(this);
- }finally {
- this.loader.loadLock.unlockWrite(id3);
- }
+ this.loader.chunkLoadQueue.remove(this);
this.loadQueue.clear();
this.loadQueue.addAll(loadQueue);
- final long id4 = this.loader.loadLock.writeLock();
- try {
- // must re-add
- this.loader.chunkLoadQueue.add(this);
- }finally {
- this.loader.loadLock.unlockWrite(id4);
- }
+ // must re-add
+ this.loader.chunkLoadQueue.add(this);
// update the chunk center
// this must be done last so that the client does not ignore any of our unload chunk packets
diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
index 36d3b0d0e1e716cb0e5a2e98c37a834776e26c20..26e1b4060f2a93cb659170f83e6ce64086e0eb0c 100644
--- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
+++ b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
@@ -6,8 +6,14 @@ import io.papermc.paper.util.CoordinateUtils;
import io.papermc.paper.util.TickThread;
import io.papermc.paper.util.WorldUtil;
import io.papermc.paper.world.ChunkEntitySlices;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMaps;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
+import it.unimi.dsi.fastutil.objects.Object2ReferenceMaps;
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import net.minecraft.core.BlockPos;
import io.papermc.paper.chunk.system.ChunkSystem;
@@ -49,17 +55,16 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
private final StampedLock entityByLock = new StampedLock();
private final StampedLock stateLock = new StampedLock();
+ //Hearse -- Just for multithreaded entity ticking
- private final ReadWriteLock paraEntityLock = new ReentrantReadWriteLock(false); //Hearse -- Just for multithreaded entity ticking
-
- protected final Long2ObjectOpenHashMap<ChunkSlicesRegion> regions = new Long2ObjectOpenHashMap<>(128, 0.5f);
+ protected final Long2ObjectMap<ChunkSlicesRegion> regions = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>(128, 0.5f));
private final int minSection; // inclusive
private final int maxSection; // inclusive
private final LevelCallback<Entity> worldCallback;
- private final Int2ReferenceOpenHashMap<Entity> entityById = new Int2ReferenceOpenHashMap<>();
- private final Object2ReferenceOpenHashMap<UUID, Entity> entityByUUID = new Object2ReferenceOpenHashMap<>();
+ private final Int2ReferenceMap<Entity> entityById = Int2ReferenceMaps.synchronize(new Int2ReferenceOpenHashMap<>());
+ private final Object2ReferenceMap<UUID, Entity> entityByUUID = Object2ReferenceMaps.synchronize(new Object2ReferenceOpenHashMap<>());
private final EntityList accessibleEntities = new EntityList();
public EntityLookup(final ServerLevel world, final LevelCallback<Entity> worldCallback) {
@@ -80,61 +85,51 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
@Nullable
@Override
public Entity get(final int id) {
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- final long attempt = this.entityByLock.tryOptimisticRead();
- if (attempt != 0L) {
- try {
- final Entity ret = this.entityById.get(id);
+ final long attempt = this.entityByLock.tryOptimisticRead();
+ if (attempt != 0L) {
+ try {
+ final Entity ret = this.entityById.get(id);
- if (this.entityByLock.validate(attempt)) {
- return maskNonAccessible(ret);
- }
- } catch (final Error error) {
- throw error;
- } catch (final Throwable thr) {
- // ignore
+ if (this.entityByLock.validate(attempt)) {
+ return maskNonAccessible(ret);
}
+ } catch (final Error error) {
+ throw error;
+ } catch (final Throwable thr) {
+ // ignore
}
+ }
- this.entityByLock.readLock();
- try {
- return maskNonAccessible(this.entityById.get(id));
- } finally {
- this.entityByLock.tryUnlockRead();
- }
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
+ this.entityByLock.readLock();
+ try {
+ return maskNonAccessible(this.entityById.get(id));
+ } finally {
+ this.entityByLock.tryUnlockRead();
}
}
@Nullable
@Override
public Entity get(final UUID id) {
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- final long attempt = this.entityByLock.tryOptimisticRead();
- if (attempt != 0L) {
- try {
- final Entity ret = this.entityByUUID.get(id);
- if (this.entityByLock.validate(attempt)) {
- return maskNonAccessible(ret);
- }
- } catch (final Error error) {
- throw error;
- } catch (final Throwable thr) {
- // ignore
+ final long attempt = this.entityByLock.tryOptimisticRead();
+ if (attempt != 0L) {
+ try {
+ final Entity ret = this.entityByUUID.get(id);
+ if (this.entityByLock.validate(attempt)) {
+ return maskNonAccessible(ret);
}
+ } catch (final Error error) {
+ throw error;
+ } catch (final Throwable thr) {
+ // ignore
}
+ }
- this.entityByLock.readLock();
- try {
- return maskNonAccessible(this.entityByUUID.get(id));
- } finally {
- this.entityByLock.tryUnlockRead();
- }
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
+ this.entityByLock.readLock();
+ try {
+ return maskNonAccessible(this.entityByUUID.get(id));
+ } finally {
+ this.entityByLock.tryUnlockRead();
}
}
@@ -143,12 +138,7 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
}
public String getDebugInfo() {
- this.paraEntityLock.readLock();//Hearse
- try {
- return "count_id:" + this.entityById.size() + ",count_uuid:" + this.entityByUUID.size() + ",region_count:" + this.regions.size();
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
- }
+ return "count_id:" + this.entityById.size() + ",count_uuid:" + this.entityByUUID.size() + ",region_count:" + this.regions.size();
}
static final class ArrayIterable<T> implements Iterable<T> {
@@ -206,30 +196,20 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
@Override
public Iterable<Entity> getAll() {
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- return new ArrayIterable<>(this.accessibleEntities.getRawData(), 0, this.accessibleEntities.size());
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
- }
+ return new ArrayIterable<>(this.accessibleEntities.getRawData(), 0, this.accessibleEntities.size());
}
@Override
public <U extends Entity> void get(final EntityTypeTest<Entity, U> filter, final AbortableIterationConsumer<U> action) {
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- for (final Entity entity : this.entityById.values()) {
- final Visibility visibility = EntityLookup.getEntityStatus(entity);
- if (!visibility.isAccessible()) {
- continue;
- }
- final U casted = filter.tryCast(entity);
- if (casted != null && action.accept(casted).shouldAbort()) {
- break;
- }
+ for (final Entity entity : this.entityById.values()) {
+ final Visibility visibility = EntityLookup.getEntityStatus(entity);
+ if (!visibility.isAccessible()) {
+ continue;
+ }
+ final U casted = filter.tryCast(entity);
+ if (casted != null && action.accept(casted).shouldAbort()) {
+ break;
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -257,55 +237,50 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
public void entityStatusChange(final Entity entity, final ChunkEntitySlices slices, final Visibility oldVisibility, final Visibility newVisibility, final boolean moved,
final boolean created, final boolean destroyed) {
TickThread.ensureTickThread(entity, "Entity status change must only happen on the main thread");
- this.paraEntityLock.writeLock().lock();//Hearse
+ final Boolean ticketBlockBefore = this.world.chunkTaskScheduler.chunkHolderManager.blockTicketUpdates();
try {
- final Boolean ticketBlockBefore = this.world.chunkTaskScheduler.chunkHolderManager.blockTicketUpdates();
- try {
- if (created) {
- EntityLookup.this.worldCallback.onCreated(entity);
- }
+ if (created) {
+ EntityLookup.this.worldCallback.onCreated(entity);
+ }
- if (oldVisibility == newVisibility) {
- if (moved && newVisibility.isAccessible()) {
- EntityLookup.this.worldCallback.onSectionChange(entity);
- }
- return;
+ if (oldVisibility == newVisibility) {
+ if (moved && newVisibility.isAccessible()) {
+ EntityLookup.this.worldCallback.onSectionChange(entity);
}
+ return;
+ }
- if (newVisibility.ordinal() > oldVisibility.ordinal()) {
- // status upgrade
- if (!oldVisibility.isAccessible() && newVisibility.isAccessible()) {
- this.accessibleEntities.add(entity);
- EntityLookup.this.worldCallback.onTrackingStart(entity);
- }
-
- if (!oldVisibility.isTicking() && newVisibility.isTicking()) {
- EntityLookup.this.worldCallback.onTickingStart(entity);
- }
- } else {
- // status downgrade
- if (oldVisibility.isTicking() && !newVisibility.isTicking()) {
- EntityLookup.this.worldCallback.onTickingEnd(entity);
- }
-
- if (oldVisibility.isAccessible() && !newVisibility.isAccessible()) {
- this.accessibleEntities.remove(entity);
- EntityLookup.this.worldCallback.onTrackingEnd(entity);
- }
+ if (newVisibility.ordinal() > oldVisibility.ordinal()) {
+ // status upgrade
+ if (!oldVisibility.isAccessible() && newVisibility.isAccessible()) {
+ this.accessibleEntities.add(entity);
+ EntityLookup.this.worldCallback.onTrackingStart(entity);
}
- if (moved && newVisibility.isAccessible()) {
- EntityLookup.this.worldCallback.onSectionChange(entity);
+ if (!oldVisibility.isTicking() && newVisibility.isTicking()) {
+ EntityLookup.this.worldCallback.onTickingStart(entity);
+ }
+ } else {
+ // status downgrade
+ if (oldVisibility.isTicking() && !newVisibility.isTicking()) {
+ EntityLookup.this.worldCallback.onTickingEnd(entity);
}
- if (destroyed) {
- EntityLookup.this.worldCallback.onDestroyed(entity);
+ if (oldVisibility.isAccessible() && !newVisibility.isAccessible()) {
+ this.accessibleEntities.remove(entity);
+ EntityLookup.this.worldCallback.onTrackingEnd(entity);
}
- } finally {
- this.world.chunkTaskScheduler.chunkHolderManager.unblockTicketUpdates(ticketBlockBefore);
+ }
+
+ if (moved && newVisibility.isAccessible()) {
+ EntityLookup.this.worldCallback.onSectionChange(entity);
+ }
+
+ if (destroyed) {
+ EntityLookup.this.worldCallback.onDestroyed(entity);
}
} finally {
- this.paraEntityLock.writeLock().lock();//Hearse
+ this.world.chunkTaskScheduler.chunkHolderManager.unblockTicketUpdates(ticketBlockBefore);
}
}
@@ -350,53 +325,48 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int sectionZ = pos.getZ() >> 4;
TickThread.ensureTickThread(this.world, sectionX, sectionZ, "Cannot add entity off-main thread");
- this.paraEntityLock.writeLock().lock();//Hearse
- try {
+ if (entity.isRemoved()) {
+ LOGGER.warn("Refusing to add removed entity: " + entity);
+ return false;
+ }
+
+ if (fromDisk) {
+ ChunkSystem.onEntityPreAdd(this.world, entity);
if (entity.isRemoved()) {
- LOGGER.warn("Refusing to add removed entity: " + entity);
+ // removed from checkDupeUUID call
return false;
}
+ }
- if (fromDisk) {
- ChunkSystem.onEntityPreAdd(this.world, entity);
- if (entity.isRemoved()) {
- // removed from checkDupeUUID call
- return false;
- }
+ this.entityByLock.writeLock();
+ try {
+ if (this.entityById.containsKey(entity.getId())) {
+ LOGGER.warn("Entity id already exists: " + entity.getId() + ", mapped to " + this.entityById.get(entity.getId()) + ", can't add " + entity);
+ return false;
}
-
- this.entityByLock.writeLock();
- try {
- if (this.entityById.containsKey(entity.getId())) {
- LOGGER.warn("Entity id already exists: " + entity.getId() + ", mapped to " + this.entityById.get(entity.getId()) + ", can't add " + entity);
- return false;
- }
- if (this.entityByUUID.containsKey(entity.getUUID())) {
- LOGGER.warn("Entity uuid already exists: " + entity.getUUID() + ", mapped to " + this.entityByUUID.get(entity.getUUID()) + ", can't add " + entity);
- return false;
- }
- this.entityById.put(entity.getId(), entity);
- this.entityByUUID.put(entity.getUUID(), entity);
- } finally {
- this.entityByLock.tryUnlockWrite();
+ if (this.entityByUUID.containsKey(entity.getUUID())) {
+ LOGGER.warn("Entity uuid already exists: " + entity.getUUID() + ", mapped to " + this.entityByUUID.get(entity.getUUID()) + ", can't add " + entity);
+ return false;
}
+ this.entityById.put(entity.getId(), entity);
+ this.entityByUUID.put(entity.getUUID(), entity);
+ } finally {
+ this.entityByLock.tryUnlockWrite();
+ }
- entity.sectionX = sectionX;
- entity.sectionY = sectionY;
- entity.sectionZ = sectionZ;
- final ChunkEntitySlices slices = this.getOrCreateChunk(sectionX, sectionZ);
- if (!slices.addEntity(entity, sectionY)) {
- LOGGER.warn("Entity " + entity + " added to world '" + this.world.getWorld().getName() + "', but was already contained in entity chunk (" + sectionX + "," + sectionZ + ")");
- }
+ entity.sectionX = sectionX;
+ entity.sectionY = sectionY;
+ entity.sectionZ = sectionZ;
+ final ChunkEntitySlices slices = this.getOrCreateChunk(sectionX, sectionZ);
+ if (!slices.addEntity(entity, sectionY)) {
+ LOGGER.warn("Entity " + entity + " added to world '" + this.world.getWorld().getName() + "', but was already contained in entity chunk (" + sectionX + "," + sectionZ + ")");
+ }
- entity.setLevelCallback(new EntityCallback(entity));
+ entity.setLevelCallback(new EntityCallback(entity));
- this.entityStatusChange(entity, slices, Visibility.HIDDEN, getEntityStatus(entity), false, !fromDisk, false);
+ this.entityStatusChange(entity, slices, Visibility.HIDDEN, getEntityStatus(entity), false, !fromDisk, false);
- return true;
- }finally {
- this.paraEntityLock.writeLock().unlock();//Hearse
- }
+ return true;
}
private void removeEntity(final Entity entity) {
@@ -407,32 +377,27 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
if (!entity.isRemoved()) {
throw new IllegalStateException("Only call Entity#setRemoved to remove an entity");
}
- this.paraEntityLock.writeLock().lock();//Hearse
- try {
- final ChunkEntitySlices slices = this.getChunk(sectionX, sectionZ);
- // all entities should be in a chunk
- if (slices == null) {
- LOGGER.warn("Cannot remove entity " + entity + " from null entity slices (" + sectionX + "," + sectionZ + ")");
- } else {
- if (!slices.removeEntity(entity, sectionY)) {
- LOGGER.warn("Failed to remove entity " + entity + " from entity slices (" + sectionX + "," + sectionZ + ")");
- }
+ final ChunkEntitySlices slices = this.getChunk(sectionX, sectionZ);
+ // all entities should be in a chunk
+ if (slices == null) {
+ LOGGER.warn("Cannot remove entity " + entity + " from null entity slices (" + sectionX + "," + sectionZ + ")");
+ } else {
+ if (!slices.removeEntity(entity, sectionY)) {
+ LOGGER.warn("Failed to remove entity " + entity + " from entity slices (" + sectionX + "," + sectionZ + ")");
}
- entity.sectionX = entity.sectionY = entity.sectionZ = Integer.MIN_VALUE;
+ }
+ entity.sectionX = entity.sectionY = entity.sectionZ = Integer.MIN_VALUE;
- this.entityByLock.writeLock();
- try {
- if (!this.entityById.remove(entity.getId(), entity)) {
- LOGGER.warn("Failed to remove entity " + entity + " by id, current entity mapped: " + this.entityById.get(entity.getId()));
- }
- if (!this.entityByUUID.remove(entity.getUUID(), entity)) {
- LOGGER.warn("Failed to remove entity " + entity + " by uuid, current entity mapped: " + this.entityByUUID.get(entity.getUUID()));
- }
- } finally {
- this.entityByLock.tryUnlockWrite();
+ this.entityByLock.writeLock();
+ try {
+ if (!this.entityById.remove(entity.getId(), entity)) {
+ LOGGER.warn("Failed to remove entity " + entity + " by id, current entity mapped: " + this.entityById.get(entity.getId()));
+ }
+ if (!this.entityByUUID.remove(entity.getUUID(), entity)) {
+ LOGGER.warn("Failed to remove entity " + entity + " by uuid, current entity mapped: " + this.entityByUUID.get(entity.getUUID()));
}
- }finally {
- this.paraEntityLock.writeLock().unlock();//Hearse
+ } finally {
+ this.entityByLock.tryUnlockWrite();
}
}
@@ -455,27 +420,22 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
// ensure the old section is owned by this tick thread
TickThread.ensureTickThread(this.world, entity.sectionX, entity.sectionZ, "Cannot move entity off-main");
- this.paraEntityLock.writeLock().lock();//Hearse
- try {
- final ChunkEntitySlices old = this.getChunk(entity.sectionX, entity.sectionZ);
- final ChunkEntitySlices slices = this.getOrCreateChunk(newSectionX, newSectionZ);
+ final ChunkEntitySlices old = this.getChunk(entity.sectionX, entity.sectionZ);
+ final ChunkEntitySlices slices = this.getOrCreateChunk(newSectionX, newSectionZ);
- if (!old.removeEntity(entity, entity.sectionY)) {
- LOGGER.warn("Could not remove entity " + entity + " from its old chunk section (" + entity.sectionX + "," + entity.sectionY + "," + entity.sectionZ + ") since it was not contained in the section");
- }
+ if (!old.removeEntity(entity, entity.sectionY)) {
+ LOGGER.warn("Could not remove entity " + entity + " from its old chunk section (" + entity.sectionX + "," + entity.sectionY + "," + entity.sectionZ + ") since it was not contained in the section");
+ }
- if (!slices.addEntity(entity, newSectionY)) {
- LOGGER.warn("Could not add entity " + entity + " to its new chunk section (" + newSectionX + "," + newSectionY + "," + newSectionZ + ") as it is already contained in the section");
- }
+ if (!slices.addEntity(entity, newSectionY)) {
+ LOGGER.warn("Could not add entity " + entity + " to its new chunk section (" + newSectionX + "," + newSectionY + "," + newSectionZ + ") as it is already contained in the section");
+ }
- entity.sectionX = newSectionX;
- entity.sectionY = newSectionY;
- entity.sectionZ = newSectionZ;
+ entity.sectionX = newSectionX;
+ entity.sectionY = newSectionY;
+ entity.sectionZ = newSectionZ;
- return slices;
- }finally {
- this.paraEntityLock.writeLock().unlock();//Hearse
- }
+ return slices;
}
public void getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
@@ -489,36 +449,31 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int maxRegionX = maxChunkX >> REGION_SHIFT;
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
- final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
- final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
+ for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
+ final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
+ final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
- for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
- final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
+ for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
+ final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
- if (region == null) {
- continue;
- }
-
- final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
- final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
+ if (region == null) {
+ continue;
+ }
- for (int currZ = minZ; currZ <= maxZ; ++currZ) {
- for (int currX = minX; currX <= maxX; ++currX) {
- final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
- if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
- continue;
- }
+ final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
+ final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
- chunk.getEntitiesWithoutDragonParts(except, box, into, predicate);
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
+ continue;
}
+
+ chunk.getEntitiesWithoutDragonParts(except, box, into, predicate);
}
}
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -533,36 +488,31 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int maxRegionX = maxChunkX >> REGION_SHIFT;
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
- final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
- final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
-
- for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
- final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
+ for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
+ final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
+ final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
- if (region == null) {
- continue;
- }
+ for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
+ final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
- final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
- final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
+ if (region == null) {
+ continue;
+ }
- for (int currZ = minZ; currZ <= maxZ; ++currZ) {
- for (int currX = minX; currX <= maxX; ++currX) {
- final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
- if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
- continue;
- }
+ final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
+ final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
- chunk.getEntities(except, box, into, predicate);
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
+ continue;
}
+
+ chunk.getEntities(except, box, into, predicate);
}
}
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -577,36 +527,31 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int maxRegionX = maxChunkX >> REGION_SHIFT;
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
- final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
- final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
-
- for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
- final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
+ for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
+ final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
+ final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
- if (region == null) {
- continue;
- }
+ for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
+ final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
- final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
- final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
+ if (region == null) {
+ continue;
+ }
- for (int currZ = minZ; currZ <= maxZ; ++currZ) {
- for (int currX = minX; currX <= maxX; ++currX) {
- final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
- if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
- continue;
- }
+ final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
+ final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
- chunk.getHardCollidingEntities(except, box, into, predicate);
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
+ continue;
}
+
+ chunk.getHardCollidingEntities(except, box, into, predicate);
}
}
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -622,36 +567,31 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int maxRegionX = maxChunkX >> REGION_SHIFT;
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
- this.paraEntityLock.readLock().lock();//Hearse
- try {
- for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
- final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
- final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
-
- for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
- final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
+ for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
+ final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
+ final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
- if (region == null) {
- continue;
- }
+ for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
+ final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
- final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
- final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
+ if (region == null) {
+ continue;
+ }
- for (int currZ = minZ; currZ <= maxZ; ++currZ) {
- for (int currX = minX; currX <= maxX; ++currX) {
- final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
- if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
- continue;
- }
+ final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
+ final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
- chunk.getEntities(type, box, (List)into, (Predicate)predicate);
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
+ continue;
}
+
+ chunk.getEntities(type, box, (List) into, (Predicate) predicate);
}
}
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -667,36 +607,31 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final int maxRegionX = maxChunkX >> REGION_SHIFT;
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
- this.paraEntityLock.readLock().unlock();//Hearse
- try {
- for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
- final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
- final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
-
- for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
- final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
+ for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
+ final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
+ final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
- if (region == null) {
- continue;
- }
+ for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
+ final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
- final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
- final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
+ if (region == null) {
+ continue;
+ }
- for (int currZ = minZ; currZ <= maxZ; ++currZ) {
- for (int currX = minX; currX <= maxX; ++currX) {
- final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
- if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
- continue;
- }
+ final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
+ final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
- chunk.getEntities(clazz, except, box, into, predicate);
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ for (int currX = minX; currX <= maxX; ++currX) {
+ final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
+ if (chunk == null || !chunk.status.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) {
+ continue;
}
+
+ chunk.getEntities(clazz, except, box, into, predicate);
}
}
}
- }finally {
- this.paraEntityLock.readLock().unlock();//Hearse
}
}
@@ -875,9 +810,11 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
public static final NoOpCallback INSTANCE = new NoOpCallback();
@Override
- public void onMove() {}
+ public void onMove() {
+ }
@Override
- public void onRemove(final Entity.RemovalReason reason) {}
+ public void onRemove(final Entity.RemovalReason reason) {
+ }
}
}
diff --git a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
index 0fd814f1d65c111266a2b20f86561839a4cef755..fe4d76875462ac9d408c972b968647af78f2ed14 100644
--- a/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
+++ b/src/main/java/io/papermc/paper/util/maplist/IteratorSafeOrderedReferenceSet.java
@@ -94,7 +94,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return 1.0 - ((double)this.indexMap.size() / (double)this.listSize);
}
- public int createRawIterator() {
+ public synchronized int createRawIterator() {
if (this.allowSafeIteration()) {
++this.iteratorCount;
}
@@ -105,7 +105,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
- public int advanceRawIterator(final int index) {
+ public synchronized int advanceRawIterator(final int index) {
final E[] elements = this.listElements;
int ret = index + 1;
for (int len = this.listSize; ret < len; ++ret) {
@@ -117,7 +117,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return -1;
}
- public void finishRawIterator() {
+ public synchronized void finishRawIterator() {
if (this.allowSafeIteration() && --this.iteratorCount == 0) {
if (this.getFragFactor() >= this.maxFragFactor) {
this.defrag();
@@ -125,7 +125,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
}
- public boolean remove(final E element) {
+ public synchronized boolean remove(final E element) {
final int index = this.indexMap.removeInt(element);
if (index >= 0) {
if (this.firstInvalidIndex < 0 || index < this.firstInvalidIndex) {
@@ -144,11 +144,11 @@ public final class IteratorSafeOrderedReferenceSet<E> {
return false;
}
- public boolean contains(final E element) {
+ public synchronized boolean contains(final E element) {
return this.indexMap.containsKey(element);
}
- public boolean add(final E element) {
+ public synchronized boolean add(final E element) {
final int listSize = this.listSize;
final int previous = this.indexMap.putIfAbsent(element, listSize);
@@ -223,30 +223,30 @@ public final class IteratorSafeOrderedReferenceSet<E> {
//this.check();
}
- public E rawGet(final int index) {
+ public synchronized E rawGet(final int index) {
return this.listElements[index];
}
- public int size() {
+ public synchronized int size() {
// always returns the correct amount - listSize can be different
return this.indexMap.size();
}
- public IteratorSafeOrderedReferenceSet.Iterator<E> iterator() {
+ public synchronized IteratorSafeOrderedReferenceSet.Iterator<E> iterator() {
return this.iterator(0);
}
- public IteratorSafeOrderedReferenceSet.Iterator<E> iterator(final int flags) {
+ public synchronized IteratorSafeOrderedReferenceSet.Iterator<E> iterator(final int flags) {
if (this.allowSafeIteration()) {
++this.iteratorCount;
}
return new BaseIterator<>(this, true, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize);
}
- public java.util.Iterator<E> unsafeIterator() {
+ public synchronized java.util.Iterator<E> unsafeIterator() {
return this.unsafeIterator(0);
}
- public java.util.Iterator<E> unsafeIterator(final int flags) {
+ public synchronized java.util.Iterator<E> unsafeIterator(final int flags) {
return new BaseIterator<>(this, false, (flags & ITERATOR_FLAG_SEE_ADDITIONS) != 0 ? Integer.MAX_VALUE : this.listSize);
}
@@ -273,7 +273,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public boolean hasNext() {
+ public synchronized boolean hasNext() {
if (this.finished) {
return false;
}
@@ -297,7 +297,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public E next() {
+ public synchronized E next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
}
@@ -310,7 +310,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public void remove() {
+ public synchronized void remove() {
final E lastReturned = this.lastReturned;
if (lastReturned == null) {
throw new IllegalStateException();
@@ -320,7 +320,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
}
@Override
- public void finishedIterating() {
+ public synchronized void finishedIterating() {
if (this.finished || !this.canFinish) {
throw new IllegalStateException();
}
diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
index f6c8dccb7f7cd287f1ebdf46481365b952baa891..ae22ca9ea5fd3d78d8c5bf9f1ab96f1129fddc11 100644
--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
+++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java
@@ -4,6 +4,7 @@ import com.destroystokyo.paper.util.maplist.EntityList;
import io.papermc.paper.chunk.system.entity.EntityLookup;
import io.papermc.paper.util.TickThread;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ChunkHolder;
@@ -35,7 +36,7 @@ public final class ChunkEntitySlices {
protected final EntityCollectionBySection allEntities;
protected final EntityCollectionBySection hardCollidingEntities;
- protected final Reference2ObjectOpenHashMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
+ protected final Reference2ObjectMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
protected final EntityList entities = new EntityList();
public ChunkHolder.FullChunkStatus status;
@@ -62,7 +63,7 @@ public final class ChunkEntitySlices {
this.allEntities = new EntityCollectionBySection(this);
this.hardCollidingEntities = new EntityCollectionBySection(this);
- this.entitiesByClass = new Reference2ObjectOpenHashMap<>();
+ this.entitiesByClass = Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>());
this.status = status;
}
@@ -199,7 +200,7 @@ public final class ChunkEntitySlices {
}
for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
if (entry.getKey().isInstance(entity)) {
@@ -224,7 +225,7 @@ public final class ChunkEntitySlices {
}
for (final Iterator<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
+ this.entitiesByClass.reference2ObjectEntrySet().iterator(); iterator.hasNext();) {
final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
if (entry.getKey().isInstance(entity)) {
@@ -302,11 +303,11 @@ public final class ChunkEntitySlices {
this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
}
- public boolean isEmpty() {
+ public synchronized boolean isEmpty() {
return this.size == 0;
}
- public int size() {
+ public synchronized int size() {
return this.size;
}
@@ -318,7 +319,7 @@ public final class ChunkEntitySlices {
}
}
- public void add(final E entity) {
+ public synchronized void add(final E entity) {
final int idx = this.size++;
if (idx >= this.storage.length) {
this.resize();
@@ -328,7 +329,7 @@ public final class ChunkEntitySlices {
}
}
- public int indexOf(final E entity) {
+ public synchronized int indexOf(final E entity) {
final E[] storage = this.storage;
for (int i = 0, len = Math.min(this.storage.length, this.size); i < len; ++i) {
@@ -340,7 +341,7 @@ public final class ChunkEntitySlices {
return -1;
}
- public boolean remove(final E entity) {
+ public synchronized boolean remove(final E entity) {
final int idx = this.indexOf(entity);
if (idx == -1) {
return false;
@@ -357,7 +358,7 @@ public final class ChunkEntitySlices {
return true;
}
- public boolean has(final E entity) {
+ public synchronized boolean has(final E entity) {
return this.indexOf(entity) != -1;
}
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 10c7d776ca0d959541d3110c75ceb45a340278ac..a23379120ddc3653b58bdb08f9c837c60b6b83ca 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1,10 +1,7 @@
package net.minecraft.server.level;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.*;
import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Queues;
import com.google.gson.JsonElement;
import com.mojang.datafixers.DataFixer;
import com.mojang.datafixers.util.Either;
@@ -103,7 +100,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public final StructureTemplateManager structureTemplateManager; // Paper - rewrite chunk system
private final String storageName;
private final PlayerMap playerMap;
- public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
+ public final Map<Integer,ChunkMap.TrackedEntity> entityMap;
private final Long2ByteMap chunkTypeCache;
private final Long2LongMap chunkSaveCooldowns;
private final Queue<Runnable> unloadQueue;
@@ -251,7 +248,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper - rewrite chunk system
this.tickingGenerated = new AtomicInteger();
this.playerMap = new PlayerMap();
- this.entityMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap());
+ this.entityMap = Maps.newConcurrentMap();
this.chunkTypeCache = Long2ByteMaps.synchronize(new Long2ByteOpenHashMap());
this.chunkSaveCooldowns = Long2LongMaps.synchronize(new Long2LongOpenHashMap());
this.unloadQueue = Queues.newConcurrentLinkedQueue();
@@ -1165,11 +1162,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ServerPlayer entityplayer = (ServerPlayer) entity;
this.updatePlayerStatus(entityplayer, true);
- ObjectIterator objectiterator = this.entityMap.values().iterator();
-
- while (objectiterator.hasNext()) {
- ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) objectiterator.next();
+ for (TrackedEntity playerchunkmap_entitytracker1 : this.entityMap.values()) {
if (playerchunkmap_entitytracker1.entity != entityplayer) {
playerchunkmap_entitytracker1.updatePlayer(entityplayer);
}
@@ -1187,11 +1181,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ServerPlayer entityplayer = (ServerPlayer) entity;
this.updatePlayerStatus(entityplayer, false);
- ObjectIterator objectiterator = this.entityMap.values().iterator();
-
- while (objectiterator.hasNext()) {
- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next();
+ for (TrackedEntity playerchunkmap_entitytracker : this.entityMap.values()) {
playerchunkmap_entitytracker.removePlayer(entityplayer);
}
}
@@ -1237,7 +1228,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper end - optimized tracker
List<ServerPlayer> list = Lists.newArrayList();
List<ServerPlayer> list1 = this.level.players();
- ObjectIterator objectiterator = this.entityMap.values().iterator();
+ Iterator objectiterator = this.entityMap.values().iterator();
//level.timings.tracker1.startTiming(); // Paper // Purpur
ChunkMap.TrackedEntity playerchunkmap_entitytracker;
diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
index 0c70810edace99bb5037d927388e055a514fcbde..0eadacb873658a0c7bd9ab24f191bc75eaebcaca 100644
--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
@@ -3,9 +3,12 @@ package net.minecraft.util.thread;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Queues;
import com.mojang.logging.LogUtils;
+
+import java.util.Deque;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.StampedLock;
@@ -20,7 +23,7 @@ import org.slf4j.Logger;
public abstract class BlockableEventLoop<R extends Runnable> implements ProfilerMeasured, ProcessorHandle<R>, Executor {
private final String name;
private static final Logger LOGGER = LogUtils.getLogger();
- private final Queue<R> pendingRunnables = Queues.newConcurrentLinkedQueue();
+ private final Deque<R> pendingRunnables = new ConcurrentLinkedDeque<>();
private final StampedLock lock = new StampedLock();
private int blockingCount;
@@ -44,12 +47,7 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
}
public int getPendingTasksCount() {
- final long id = this.lock.readLock();
- try{
- return this.pendingRunnables.size();
- }finally {
- this.lock.unlockRead(id);
- }
+ return this.pendingRunnables.size();
}
@Override
@@ -95,12 +93,7 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
@Override
public void tell(R runnable) {
- final long id = this.lock.writeLock();
- try {
- this.pendingRunnables.add(runnable);
- }finally {
- this.lock.unlockWrite(id);
- }
+ this.pendingRunnables.add(runnable);
LockSupport.unpark(this.getRunningThread());
}
@@ -119,12 +112,7 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
}
protected void dropAllTasks() {
- final long id = this.lock.writeLock();
- try {
- this.pendingRunnables.clear();
- }finally {
- this.lock.unlockWrite(id);
- }
+ this.pendingRunnables.clear();
}
protected void runAllTasks() {
@@ -134,19 +122,15 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
}
public boolean pollTask() {
- final long id = this.lock.writeLock();
- try {
- R runnable = this.pendingRunnables.peek();
- if (runnable == null) {
- return false;
- } else if (this.blockingCount == 0 && !this.shouldRun(runnable)) {
- return false;
- } else {
- this.doRunTask(this.pendingRunnables.remove());
- return true;
- }
- }finally {
- this.lock.unlockWrite(id);
+ R runnable = this.pendingRunnables.poll();
+ if (runnable == null) {
+ return false;
+ } else if (this.blockingCount == 0 && !this.shouldRun(runnable)) {
+ this.pendingRunnables.addFirst(runnable);
+ return false;
+ } else {
+ this.doRunTask(runnable);
+ return true;
}
}
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
index 00f7b58db5948f4d7c7f07736d8fcf1972009c77..dca7c7f83043452b5fef3c1d24a99f08dfaf242a 100644
--- a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
+++ b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
@@ -1,14 +1,15 @@
package net.minecraft.world.level.entity;
-import java.util.Iterator;
-import java.util.Set;
+import java.util.*;
import java.util.function.Consumer;
+
+import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import net.minecraft.world.entity.Entity;
public class EntityTickList {
- public final Set<Entity> entities = ObjectSets.synchronize(new ObjectArraySet<>());
+ public final List<Entity> entities = Lists.newCopyOnWriteArrayList();
public void add(Entity entity) {
io.papermc.paper.util.TickThread.ensureTickThread("Asynchronous entity ticklist addition"); // Paper
diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
index a097e00bd62f53630568f68854d3a34300012277..799cd9d04d156ed87e9b1dfde75ae15280c9eb0d 100644
--- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
+++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
@@ -22,8 +22,6 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
private final List<CollectingNeighborUpdater.NeighborUpdates> addedThisLayer = new CopyOnWriteArrayList<>();
private int count = 0;
- private final StampedLock lock = new StampedLock();
-
public CollectingNeighborUpdater(Level world, int maxChainDepth) {
this.level = world;
this.maxChainedNeighborUpdates = maxChainDepth;
@@ -49,23 +47,18 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
this.addAndRun(pos, new CollectingNeighborUpdater.MultiNeighborUpdate(pos.immutable(), sourceBlock, except));
}
- private void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates entry) {
+ private synchronized void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates entry) {
boolean bl = this.count > 0;
boolean bl2 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates;
++this.count;
- final long lockId = this.lock.writeLock();
- try {
- if (!bl2) {
- if (bl) {
- this.addedThisLayer.add(entry);
- } else {
- this.stack.push(entry);
- }
- } else if (this.count - 1 == this.maxChainedNeighborUpdates) {
- LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString());
+ if (!bl2) {
+ if (bl) {
+ this.addedThisLayer.add(entry);
+ } else {
+ this.stack.push(entry);
}
- }finally {
- this.lock.unlockWrite(lockId);
+ } else if (this.count - 1 == this.maxChainedNeighborUpdates) {
+ LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString());
}
if (!bl) {
@@ -75,30 +68,25 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
}
private void runUpdates() {
- final long lockid = this.lock.writeLock();
try {
- try {
- while(!this.stack.isEmpty() || !this.addedThisLayer.isEmpty()) {
- for(int i = this.addedThisLayer.size() - 1; i >= 0; --i) {
- this.stack.push(this.addedThisLayer.get(i));
- }
- this.addedThisLayer.clear();
- CollectingNeighborUpdater.NeighborUpdates neighborUpdates = this.stack.peek();
-
- while(this.addedThisLayer.isEmpty()) {
- if (!neighborUpdates.runNext(this.level)) {
- this.stack.pop();
- break;
- }
- }
+ while (!this.stack.isEmpty() || !this.addedThisLayer.isEmpty()) {
+ for (int i = this.addedThisLayer.size() - 1; i >= 0; --i) {
+ this.stack.push(this.addedThisLayer.get(i));
}
- } finally {
- this.stack.clear();
this.addedThisLayer.clear();
- this.count = 0;
+ CollectingNeighborUpdater.NeighborUpdates neighborUpdates = this.stack.peek();
+
+ while (this.addedThisLayer.isEmpty()) {
+ if (!neighborUpdates.runNext(this.level)) {
+ this.stack.pop();
+ break;
+ }
+ }
}
- }finally {
- this.lock.unlockWrite(lockid);
+ } finally {
+ this.stack.clear();
+ this.addedThisLayer.clear();
+ this.count = 0;
}
}