diff --git a/gradle.properties b/gradle.properties index a096cb3..3a1f46b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,4 +5,4 @@ org.gradle.vfs.watch=false group=host.bloom.petal version=1.19.2-R0.1-SNAPSHOT mcVersion=1.19.2 -purpurRef=0008a68c1be431a9253cfd23ac778ffbc4d78cc4 +purpurRef=cf6b7c345980e35d47bfc1382c5aa34c21eebe61 diff --git a/patches/server/0001-conf-brand-server-to-petal.patch b/patches/server/0001-conf-brand-server-to-petal.patch index 6c2cc09..0669f77 100644 --- a/patches/server/0001-conf-brand-server-to-petal.patch +++ b/patches/server/0001-conf-brand-server-to-petal.patch @@ -5,7 +5,7 @@ Subject: [PATCH] conf: brand server to petal diff --git a/build.gradle.kts b/build.gradle.kts -index 441a18132eb60e1af8b624ab7cf3de61669ced1f..27b3535f53c1de721b71e04c80688e1907230178 100644 +index 2ee34f92e8a89b90448bbf710fdc0d5d6350e919..d7cd4c85a8775f979f62d5da7220a1be321743a6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { @@ -17,7 +17,7 @@ index 441a18132eb60e1af8b624ab7cf3de61669ced1f..27b3535f53c1de721b71e04c80688e19 // Pufferfish start implementation("io.papermc.paper:paper-mojangapi:1.19.2-R0.1-SNAPSHOT") { exclude("io.papermc.paper", "paper-api") -@@ -87,7 +87,7 @@ tasks.jar { +@@ -86,7 +86,7 @@ tasks.jar { attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "CraftBukkit", @@ -84,10 +84,10 @@ index fba5dbdb7bcbb55400ef18342c9b54612972a718..3f9aa4292ff45c6b6af0ddfeecb645f8 switch (distance) { case -1: diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d7c77908ba7f0a0c00c06744d1ee0c1ad3ee0d7c..8527b1d2c559ce9c4608725dd455a000c75d0333 100644 +index 13c9cddf7ac0af16676050e3bcdf22b7475a0387..abc5a4a67270db2b801d02fe870e73b448fac9a7 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -916,7 +916,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0.75F ? this.mob.getBbWidth() / 2.0F : 0.75F - this.mob.getBbWidth() / 2.0F; Vec3i vec3i = this.path.getNextNodePos(); -@@ -439,7 +454,7 @@ public abstract class PathNavigation { - // Paper start - public boolean isViableForPathRecalculationChecking() { - return !this.needsPathRecalculation() && -- (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0); -+ (this.path != null && this.path.isProcessed() && !this.path.isDone() && this.path.getNodeCount() != 0); - } - // Paper end - } +@@ -419,7 +434,7 @@ public abstract class PathNavigation { + public boolean shouldRecomputePath(BlockPos pos) { + if (this.hasDelayedRecomputation) { + return false; +- } else if (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0) { ++ } else if (this.path != null && this.path.isProcessed() && !this.path.isDone() && this.path.getNodeCount() != 0) { // petal + Node node = this.path.getEndNode(); + Vec3 vec3 = new Vec3(((double)node.x + this.mob.getX()) / 2.0D, ((double)node.y + this.mob.getY()) / 2.0D, ((double)node.z + this.mob.getZ()) / 2.0D); + return pos.closerToCenterThan(vec3, (double)(this.path.getNodeCount() - this.path.getNextNodeIndex())); diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java index 8db20db72cd51046213625fac46c35854c59ec5d..11b386697279333ffd5f3abc9e1dbc9c19711764 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java @@ -869,7 +869,7 @@ index 8db20db72cd51046213625fac46c35854c59ec5d..11b386697279333ffd5f3abc9e1dbc9c } } diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 6e33790792e8d0b727fce7dd3bf8a848ca5180a3..d29c9121dc3cb1780c7d25e18f220daf8c25c6e1 100644 +index 3241815b0a5584a005457657660d2bb426b0fcdb..3dee1536034753b0d457b65a2944b398b4e748e1 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java @@ -1146,7 +1146,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { diff --git a/patches/server/0003-feat-multithreaded-tracker.patch b/patches/server/0003-feat-multithreaded-tracker.patch index a5f99e7..bce6ebf 100644 --- a/patches/server/0003-feat-multithreaded-tracker.patch +++ b/patches/server/0003-feat-multithreaded-tracker.patch @@ -4,6 +4,7 @@ Date: Sat, 2 Jul 2022 00:35:56 -0500 Subject: [PATCH] feat: multithreaded tracker Co-authored-by: Paul Sauve +Co-authored-by: Kevin Raneri based off the airplane multithreaded tracker this patch properly handles concurrent accesses everywhere, as well as being much simpler to maintain @@ -11,12 +12,15 @@ concurrent accesses everywhere, as well as being much simpler to maintain some things are too unsafe to run off the main thread so we don't attempt to do that. this multithreaded tracker remains accurate, non-breaking and fast +we also learned from pufferfish core that changes have to be sent ordered +now we do that in an optimized way + diff --git a/src/main/java/host/bloom/tracker/MultithreadedTracker.java b/src/main/java/host/bloom/tracker/MultithreadedTracker.java new file mode 100644 -index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e0467ee8fd3 +index 0000000000000000000000000000000000000000..d27b7224ed2bcc63386dc46c33bfb8b272d91f92 --- /dev/null +++ b/src/main/java/host/bloom/tracker/MultithreadedTracker.java -@@ -0,0 +1,128 @@ +@@ -0,0 +1,154 @@ +package host.bloom.tracker; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -34,6 +38,11 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + +public class MultithreadedTracker { + ++ private enum TrackerStage { ++ UPDATE_PLAYERS, ++ SEND_CHANGES ++ } ++ + private static final int parallelism = Math.max(4, Runtime.getRuntime().availableProcessors()); + private static final Executor trackerExecutor = Executors.newFixedThreadPool(parallelism, new ThreadFactoryBuilder() + .setNameFormat("petal-tracker-%d") @@ -58,17 +67,18 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + return; + } + ++ // start with updating players + try { + this.taskIndex.set(iterator); + this.finishedTasks.set(0); + + for (int i = 0; i < parallelism; i++) { -+ trackerExecutor.execute(this::run); ++ trackerExecutor.execute(this::runUpdatePlayers); + } + + while (this.taskIndex.get() < this.entityTickingChunks.getListSize()) { + this.runMainThreadTasks(); -+ this.handleTasks(5); // assist ++ this.handleChunkUpdates(5); // assist + } + + while (this.finishedTasks.get() != parallelism) { @@ -79,6 +89,25 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + } finally { + this.entityTickingChunks.finishRawIterator(); + } ++ ++ // then send changes ++ iterator = this.entityTickingChunks.createRawIterator(); ++ ++ if (iterator == -1) { ++ return; ++ } ++ ++ try { ++ do { ++ LevelChunk chunk = this.entityTickingChunks.rawGet(iterator); ++ ++ if (chunk != null) { ++ this.updateChunkEntities(chunk, TrackerStage.SEND_CHANGES); ++ } ++ } while (++iterator < this.entityTickingChunks.getListSize()); ++ } finally { ++ this.entityTickingChunks.finishRawIterator(); ++ } + } + + private void runMainThreadTasks() { @@ -92,22 +121,22 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + } + } + -+ private void run() { ++ private void runUpdatePlayers() { + try { -+ while (handleTasks(10)); ++ while (handleChunkUpdates(10)); + } finally { + this.finishedTasks.incrementAndGet(); + } + } + -+ private boolean handleTasks(int tasks) { ++ private boolean handleChunkUpdates(int tasks) { + int index; + while ((index = this.taskIndex.getAndAdd(tasks)) < this.entityTickingChunks.getListSize()) { + for (int i = index; i < index + tasks && i < this.entityTickingChunks.getListSize(); i++) { + LevelChunk chunk = this.entityTickingChunks.rawGet(i); + if (chunk != null) { + try { -+ this.processChunk(chunk); ++ this.updateChunkEntities(chunk, TrackerStage.UPDATE_PLAYERS); + } catch (Throwable throwable) { + MinecraftServer.LOGGER.warn("Ticking tracker failed", throwable); + } @@ -121,8 +150,8 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + return false; + } + -+ private void processChunk(LevelChunk chunk) { -+ final ChunkEntitySlices entitySlices = chunk.level.entityManager.entitySliceManager.getChunk(chunk.locX, chunk.locZ); ++ private void updateChunkEntities(LevelChunk chunk, TrackerStage trackerStage) { ++ final ChunkEntitySlices entitySlices = chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ); + if (entitySlices == null) { + return; + } @@ -135,10 +164,11 @@ index 0000000000000000000000000000000000000000..31a9a1dbb68cdbc5dc8a83542ddc7e04 + if (entity != null) { + ChunkMap.TrackedEntity entityTracker = chunkMap.entityMap.get(entity.getId()); + if (entityTracker != null) { -+ entityTracker.updatePlayers(entityTracker.entity.getPlayersInTrackRange()); -+ -+ // run this on the main thread but queue it up here so we can run it while processing tracking at the same time -+ this.mainThreadTasks.offer(entityTracker.serverEntity::sendChanges); ++ if (trackerStage == TrackerStage.SEND_CHANGES) { ++ entityTracker.serverEntity.sendChanges(); ++ } else if (trackerStage == TrackerStage.UPDATE_PLAYERS) { ++ entityTracker.updatePlayers(entityTracker.entity.getPlayersInTrackRange()); ++ } + } + } + } @@ -159,10 +189,10 @@ index 0fd814f1d65c111266a2b20f86561839a4cef755..169ac3ad1b1e8e3e1874ada2471e4782 protected final double maxFragFactor; diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java -index 47b5f75d9f27cf3ab947fd1f69cbd609fb9f2749..85882eeb86d7b74db0219aa65783946d8083885d 100644 +index f597d65d56964297eeeed6c7e77703764178fee0..665c377e2d0d342f4dcc89c4cbdfcc9e4b96e95c 100644 --- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java -@@ -27,7 +27,7 @@ public final class ChunkEntitySlices { +@@ -35,7 +35,7 @@ public final class ChunkEntitySlices { protected final EntityCollectionBySection allEntities; protected final EntityCollectionBySection hardCollidingEntities; protected final Reference2ObjectOpenHashMap, EntityCollectionBySection> entitiesByClass; @@ -172,10 +202,10 @@ index 47b5f75d9f27cf3ab947fd1f69cbd609fb9f2749..85882eeb86d7b74db0219aa65783946d public ChunkHolder.FullChunkStatus status; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 4fa383ff6ef3a9cc59b73ea4f52ae02e90140d2a..5293b7afb82b8250e07bc1d99cd837570e68c731 100644 +index 3203b953709ca7cb9172f5912a922131ad7ec9eb..b39a01b903eafa15a2fc758bc74fa9b0f9b5fd5b 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -2077,8 +2077,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1237,8 +1237,27 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = null; // Paper - We're no longer tracked } @@ -203,7 +233,7 @@ index 4fa383ff6ef3a9cc59b73ea4f52ae02e90140d2a..5293b7afb82b8250e07bc1d99cd83757 //this.level.timings.tracker1.startTiming(); // Purpur try { for (TrackedEntity tracker : this.entityMap.values()) { -@@ -2349,11 +2368,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1462,11 +1481,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public class TrackedEntity { @@ -218,7 +248,7 @@ index 4fa383ff6ef3a9cc59b73ea4f52ae02e90140d2a..5293b7afb82b8250e07bc1d99cd83757 public TrackedEntity(Entity entity, int i, int j, boolean flag) { this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit -@@ -2365,7 +2384,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1478,7 +1497,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper start - use distance map to optimise tracker com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; @@ -227,7 +257,7 @@ index 4fa383ff6ef3a9cc59b73ea4f52ae02e90140d2a..5293b7afb82b8250e07bc1d99cd83757 com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; this.lastTrackerCandidates = newTrackerCandidates; -@@ -2437,7 +2456,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1550,7 +1569,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void removePlayer(ServerPlayer player) { @@ -236,7 +266,7 @@ index 4fa383ff6ef3a9cc59b73ea4f52ae02e90140d2a..5293b7afb82b8250e07bc1d99cd83757 if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); } -@@ -2445,7 +2464,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1558,7 +1577,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void updatePlayer(ServerPlayer player) { diff --git a/patches/server/0004-feat-reduce-work-done-by-game-event-system.patch b/patches/server/0004-feat-reduce-work-done-by-game-event-system.patch index 63e55c1..428e9bb 100644 --- a/patches/server/0004-feat-reduce-work-done-by-game-event-system.patch +++ b/patches/server/0004-feat-reduce-work-done-by-game-event-system.patch @@ -8,10 +8,10 @@ Subject: [PATCH] feat: reduce work done by game event system 2. euclideangameeventdispatcher is not used concurrently so we ban that usage for improved performance with allays diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 6859e2054e8eb4fc8ac005e0bf646a30defa47a6..420597ee691a38e2cb71008ec6666fb54892c68d 100644 +index 571a1cbee376032b6b9f36c9fe3f9199a3ad3197..92e7ba78e18efb8263475ecc076bc49e88b85e84 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1678,6 +1678,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1703,6 +1703,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (chunk != null) { for (int j2 = k; j2 <= j1; ++j2) { flag |= chunk.getEventDispatcher(j2).walkListeners(event, emitterPos, emitter, (gameeventlistener, vec3d1) -> { @@ -38,7 +38,7 @@ index 22c309343299e60ed8028229b7f134109001ff35..d5947d29295ddc93ba8ac1c0fc61f7ba org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. blockEntity.sculkSpreader.updateCursors(world, pos, world.getRandom(), true); 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 12293740461b6cd965297543a1ae3bead83bd3a6..eeb96c486378cd21f7d54ddc20a5aa6bd1b4dc3e 100644 +index 620173eef4c2f30a97a4c2f8049ea01fcc60d0b2..bdf67c916fe435f3bd04a61cce6db93c606515ce 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -84,7 +84,18 @@ public class LevelChunk extends ChunkAccess { @@ -60,8 +60,8 @@ index 12293740461b6cd965297543a1ae3bead83bd3a6..eeb96c486378cd21f7d54ddc20a5aa6b + // petal end private final LevelChunkTicks blockTicks; private final LevelChunkTicks fluidTicks; - // Paper start - track last save time -@@ -119,7 +130,7 @@ public class LevelChunk extends ChunkAccess { + +@@ -113,7 +124,7 @@ public class LevelChunk extends ChunkAccess { this.tickersInLevel = Maps.newHashMap(); this.clientLightReady = false; this.level = (ServerLevel) world; // CraftBukkit - type @@ -70,7 +70,7 @@ index 12293740461b6cd965297543a1ae3bead83bd3a6..eeb96c486378cd21f7d54ddc20a5aa6b Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); int j = aheightmap_type.length; -@@ -453,9 +464,23 @@ public class LevelChunk extends ChunkAccess { +@@ -446,9 +457,23 @@ public class LevelChunk extends ChunkAccess { if (world instanceof ServerLevel) { ServerLevel worldserver = (ServerLevel) world; @@ -97,7 +97,7 @@ index 12293740461b6cd965297543a1ae3bead83bd3a6..eeb96c486378cd21f7d54ddc20a5aa6b } else { return super.getEventDispatcher(ySectionCoord); } -@@ -819,7 +844,7 @@ public class LevelChunk extends ChunkAccess { +@@ -812,7 +837,7 @@ public class LevelChunk extends ChunkAccess { gameeventdispatcher.unregister(gameeventlistener); if (gameeventdispatcher.isEmpty()) {