mirror of
https://github.com/SparklyPower/SparklyPaper.git
synced 2025-12-21 07:59:31 +00:00
135 lines
7.9 KiB
Diff
135 lines
7.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: MrPowerGamerBR <git@mrpowergamerbr.com>
|
|
Date: Sun, 26 Nov 2023 13:11:10 -0300
|
|
Subject: [PATCH] Optimize tickBlockEntities
|
|
|
|
We cache the last `shouldTickBlocksAt` result, because the `shouldTickBlocksAt` is expensive because it requires pulling chunk holder info from an map for each block entity (even if the block entities are on the same chunk!) every single time. So, if the last chunk position is the same as our cached value, we use the last cached `shouldTickBlocksAt` result!
|
|
|
|
We could use a map for caching, but here's why this is way better than using a map: The block entity ticking list is sorted by chunks! Well, sort of... It is sorted by chunk when the chunk has been loaded, newly placed blocks will be appended to the end of the list until the chunk unloads and loads again. Most block entities are things that players placed to be there for a long time anyway (like hoppers, etc)
|
|
|
|
But here's the thing: We don't care if we have a small performance penalty if the players have placed new block entities, the small performance hit of when a player placed new block entities is so small ('tis just a long comparsion after all), that the performance boost from already placed block entities is bigger, this helps a lot if your server has a lot of chunks with multiple block entities, and the block entities will be automatically sorted after the chunk is unloaded and loaded again, so it ain't that bad.
|
|
|
|
And finally, we also cache the chunk's coordinate key when creating the block entity, which is actually "free" because we just reuse the already cached chunk coordinate key from the chunk!
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 0bccd7c93aaaac1f8441065361546062f3a6b962..fcb7c4937fc7684c0f5d9677af9c276fedb20361 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -1285,6 +1285,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
boolean flag = this.tickRateManager().runsNormally();
|
|
|
|
int tilesThisCycle = 0;
|
|
+ // SparklyPaper start - optimize tickBlockEntities
|
|
+ int shouldTickBlocksAtLastResult = -1; // -1 = undefined
|
|
+ long shouldTickBlocksAtChunkPos = 0L;
|
|
+ // SparklyPaper end
|
|
for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
|
|
this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
|
|
TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(this.tileTickPosition);
|
|
@@ -1295,13 +1299,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
tilesThisCycle--;
|
|
this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // this.blockEntityTickers.remove(this.tileTickPosition--); // SparklyPaper - optimize block entity removals
|
|
// Spigot end
|
|
- } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) {
|
|
+ // } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { // SparklyPaper start - optimize tickBlockEntities
|
|
+ } else if (flag) {
|
|
+ long chunkPos = tickingblockentity.getChunkCoordinateKey();
|
|
+ boolean shouldTick;
|
|
+ if (shouldTickBlocksAtChunkPos == chunkPos && shouldTickBlocksAtLastResult != -1) {
|
|
+ shouldTick = shouldTickBlocksAtLastResult == 1;
|
|
+ } else {
|
|
+ shouldTick = this.shouldTickBlocksAt(chunkPos);
|
|
+ shouldTickBlocksAtLastResult = shouldTick ? 1 : 0;
|
|
+ shouldTickBlocksAtChunkPos = chunkPos;
|
|
+ }
|
|
+ if (shouldTick) {
|
|
tickingblockentity.tick();
|
|
// Paper start - execute chunk tasks during tick
|
|
if ((this.tileTickPosition & 7) == 0) {
|
|
MinecraftServer.getServer().executeMidTickTasks();
|
|
}
|
|
// Paper end - execute chunk tasks during tick
|
|
+ } // SparklyPaper end
|
|
}
|
|
}
|
|
this.blockEntityTickers.removeMarkedEntries(); // SparklyPaper - optimize block entity removals
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TickingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
index 28e3b73507b988f7234cbf29c4024c88180d0aef..427cf73383155c52bca8fb4b32f43029ff619833 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
@@ -10,4 +10,6 @@ public interface TickingBlockEntity {
|
|
BlockPos getPos();
|
|
|
|
String getType();
|
|
+
|
|
+ long getChunkCoordinateKey(); // SparklyPaper - optimize tickBlockEntities
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
index 465458e8a7dbaf9afb32709a71c7b2620d1e1fd2..5fc876f1fa9a64eb2fcc33b48c0f8bdf82bd2c24 100644
|
|
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
|
@@ -73,6 +73,13 @@ public class LevelChunk extends ChunkAccess {
|
|
public String getType() {
|
|
return "<null>";
|
|
}
|
|
+
|
|
+ // SparklyPaper start - optimize tickBlockEntities
|
|
+ @Override
|
|
+ public long getChunkCoordinateKey() {
|
|
+ return 0;
|
|
+ }
|
|
+ // SparklyPaper end
|
|
};
|
|
private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel;
|
|
public boolean loaded;
|
|
@@ -1089,7 +1096,7 @@ public class LevelChunk extends ChunkAccess {
|
|
}
|
|
|
|
private <T extends BlockEntity> TickingBlockEntity createTicker(T blockEntity, BlockEntityTicker<T> blockEntityTicker) {
|
|
- return new LevelChunk.BoundTickingBlockEntity<>(blockEntity, blockEntityTicker);
|
|
+ return new LevelChunk.BoundTickingBlockEntity<>(blockEntity, blockEntityTicker, this.coordinateKey); // SparklyPaper - optimize tickBlockEntities
|
|
}
|
|
|
|
@FunctionalInterface
|
|
@@ -1140,6 +1147,13 @@ public class LevelChunk extends ChunkAccess {
|
|
public String toString() {
|
|
return this.ticker + " <wrapped>";
|
|
}
|
|
+
|
|
+ // SparklyPaper start - optimize tickBlockEntities
|
|
+ @Override
|
|
+ public long getChunkCoordinateKey() {
|
|
+ return this.ticker.getChunkCoordinateKey();
|
|
+ }
|
|
+ // SparklyPaper end
|
|
}
|
|
|
|
private class BoundTickingBlockEntity<T extends BlockEntity> implements TickingBlockEntity {
|
|
@@ -1147,10 +1161,12 @@ public class LevelChunk extends ChunkAccess {
|
|
private final T blockEntity;
|
|
private final BlockEntityTicker<T> ticker;
|
|
private boolean loggedInvalidBlockState;
|
|
+ private final long chunkCoordinateKey; // SparklyPaper - optimize tickBlockEntities
|
|
|
|
- BoundTickingBlockEntity(BlockEntity tileentity, BlockEntityTicker blockentityticker) {
|
|
+ BoundTickingBlockEntity(BlockEntity tileentity, BlockEntityTicker blockentityticker, long chunkCoordinateKey) { // SparklyPaper - optimize tickBlockEntities
|
|
this.blockEntity = (T) tileentity; // CraftBukkit - decompile error
|
|
this.ticker = blockentityticker;
|
|
+ this.chunkCoordinateKey = chunkCoordinateKey; // SparklyPaper - optimize tickBlockEntities
|
|
}
|
|
|
|
@Override
|
|
@@ -1218,5 +1234,12 @@ public class LevelChunk extends ChunkAccess {
|
|
|
|
return "Level ticker for " + s + "@" + this.getPos();
|
|
}
|
|
+
|
|
+ // SparklyPaper start - optimize tickBlockEntities
|
|
+ @Override
|
|
+ public long getChunkCoordinateKey() {
|
|
+ return this.chunkCoordinateKey;
|
|
+ }
|
|
+ // SparklyPaper end
|
|
}
|
|
}
|