9
0
mirror of https://github.com/BX-Team/DivineMC.git synced 2025-12-19 14:59:25 +00:00

update rct patch

This commit is contained in:
NONPLAYT
2025-06-10 21:19:58 +03:00
parent a51a8781e0
commit 98685c13ee
19 changed files with 404 additions and 142 deletions

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Async Chunk Sending
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
index 76b8d42ae530b59cdaba0583365a557da6b90ede..235772cc9a7c878235b97c8d84cacda3016f91ca 100644 index 886825a10bd06b4b656d19a05624c74f2686feb3..1f3f15e3c3eb2c8e71caba069b457cec53f635f2 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java --- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -55,6 +55,8 @@ public final class RegionizedPlayerChunkLoader { @@ -55,6 +55,8 @@ public final class RegionizedPlayerChunkLoader {

View File

@@ -1,114 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Mon, 24 Feb 2025 19:58:39 +0300
Subject: [PATCH] Regionized Chunk Ticking
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index ae0e36d198ad8243920c8e8a55c0be4945542763..7f982949304535376dabf42aab1848cabc8987cf 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -54,6 +54,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private static final Logger LOGGER = LogUtils.getLogger();
private final DistanceManager distanceManager;
private final ServerLevel level;
+ // DivineMC - Regionized Chunk Ticking
+ public static final Executor REGION_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadCount, new org.bxteam.divinemc.util.NamedAgnosticThreadFactory<>("region_ticking", ca.spottedleaf.moonrise.common.util.TickThread::new, org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadPriority));
+ public volatile int tickingRegionsCount = 0;
+ // DivineMC end - Regionized Chunk Ticking
public final Thread mainThread;
final ThreadedLevelLightEngine lightEngine;
public final ServerChunkCache.MainThreadExecutor mainThreadProcessor;
@@ -461,6 +465,46 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(save, true); // Paper - rewrite chunk system
}
+ // DivineMC start - Regionized Chunk Ticking
+ private static final int[] DX = {1, -1, 0, 0, 1, -1, -1, 1};
+ private static final int[] DZ = {0, 0, 1, -1, 1, 1, -1, -1};
+
+ private List<LevelChunk>[] splitChunksIntoRegions(List<LevelChunk> chunks) {
+ int size = chunks.size();
+ java.util.IdentityHashMap<LevelChunk, Boolean> chunkSet = new java.util.IdentityHashMap<>(size);
+
+ for (LevelChunk chunk : chunks) {
+ chunkSet.put(chunk, Boolean.TRUE);
+ }
+
+ List<List<LevelChunk>> groups = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(size >> 3);
+ LevelChunk[] stack = new LevelChunk[size];
+ int stackPointer = 0;
+
+ for (LevelChunk chunk : chunks) {
+ if (chunkSet.remove(chunk) == null) continue;
+
+ List<LevelChunk> group = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(64);
+ stack[stackPointer++] = chunk;
+
+ while (stackPointer > 0) {
+ LevelChunk current = stack[--stackPointer];
+ group.add(current);
+
+ for (int i = 0; i < 8; i++) {
+ LevelChunk neighbor = getChunk(current.locX + DX[i], current.locZ + DZ[i], false);
+ if (neighbor == null || chunkSet.remove(neighbor) == null) continue;
+ stack[stackPointer++] = neighbor;
+ }
+ }
+
+ groups.add(group);
+ }
+
+ return groups.toArray(new List[0]);
+ }
+ // DivineMC end - Regionized Chunk Ticking
+
@Override
public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) {
if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
@@ -492,7 +536,44 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
this.shuffleRandom.setSeed(this.level.random.nextLong());
if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
// Paper end - chunk tick iteration optimisation
- this.tickChunks(l, list);
+ // DivineMC start - Regionized Chunk Ticking
+ if (org.bxteam.divinemc.DivineConfig.enableRegionizedChunkTicking) {
+ List<LevelChunk>[] regions = splitChunksIntoRegions(list);
+ int regionCount = regions.length;
+ this.tickingRegionsCount = regionCount;
+ java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(regionCount);
+
+ try {
+ java.util.concurrent.ForkJoinPool.managedBlock(new java.util.concurrent.ForkJoinPool.ManagedBlocker() {
+ @Override
+ public boolean block() throws InterruptedException {
+ for (List<LevelChunk> region : regions) {
+ if (region == null) continue;
+ REGION_EXECUTOR.execute(() -> {
+ try {
+ tickChunks(l, region);
+ } finally {
+ latch.countDown();
+ }
+ });
+ }
+
+ latch.await();
+ return true;
+ }
+
+ @Override
+ public boolean isReleasable() {
+ return latch.getCount() == 0;
+ }
+ });
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("Interrupted managed block during region ticking", ex);
+ }
+ } else {
+ this.tickChunks(l, list);
+ }
+ // DivineMC end - Regionized Chunk Ticking
} finally {
list.clear();
}

View File

@@ -23,7 +23,7 @@ index b402f6a6ecb8047bbb791b212fba375f4c9e6af5..f381f3ecd27315e06ca6883006a8a4c3
player.awardStat(Stats.ITEM_USED.get(item)); player.awardStat(Stats.ITEM_USED.get(item));
// level.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit // level.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit
diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java
index c8c8351f5645cf4041d26b0e02c072546ad329c6..75a695aaf0dd2f58e1fa5e1c532ae298c2a2abdb 100644 index 075987ec1eabb7385918049c54d7210ff2b38847..d7488164313cbf038ff7669da275bfdb41e8343c 100644
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java --- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -727,13 +727,25 @@ public interface DispenseItemBehavior { @@ -727,13 +727,25 @@ public interface DispenseItemBehavior {

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Leaf: Improve BlockEntity ticking isRemoved check
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 0337f4b9ca3c9c9a1e2a7cf19fcbad5e78b949dc..1820069a7c5833b0a13e034c232f06af234788e3 100644 index 534384727e852dc8ea822f49f182af49eb3a40c1..d779ff76432e498123ed1d70946a9833c939b754 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java --- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -989,13 +989,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @@ -989,13 +989,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p

View File

@@ -22,10 +22,10 @@ Example config in paper-world-defaults.yml:
``` ```
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070e1cbaf1f 100644 index d3f5242fc66529bf3137da4d505a6cf55e749e43..1056a17c53e7d16d5fba7f9a354dfbc235d4d974 100644
--- a/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -175,29 +175,52 @@ public final class NaturalSpawner { @@ -164,29 +164,52 @@ public final class NaturalSpawner {
// Copied from getFilteredSpawningCategories // Copied from getFilteredSpawningCategories
int limit = mobCategory.getMaxInstancesPerChunk(); int limit = mobCategory.getMaxInstancesPerChunk();
SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory); SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
@@ -91,7 +91,7 @@ index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070
// Paper end - Optional per player mob spawns // Paper end - Optional per player mob spawns
} }
} }
@@ -221,12 +244,21 @@ public final class NaturalSpawner { @@ -210,12 +233,21 @@ public final class NaturalSpawner {
} }
public static void spawnCategoryForChunk( public static void spawnCategoryForChunk(
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity
@@ -114,7 +114,7 @@ index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070
} }
@VisibleForDebug @VisibleForDebug
@@ -246,16 +278,22 @@ public final class NaturalSpawner { @@ -235,16 +267,22 @@ public final class NaturalSpawner {
} }
public static void spawnCategoryForPosition( public static void spawnCategoryForPosition(
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity
@@ -139,7 +139,7 @@ index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070
for (int i1 = 0; i1 < 3; i1++) { for (int i1 = 0; i1 < 3; i1++) {
int x = pos.getX(); int x = pos.getX();
int z = pos.getZ(); int z = pos.getZ();
@@ -295,13 +333,13 @@ public final class NaturalSpawner { @@ -284,13 +322,13 @@ public final class NaturalSpawner {
} }
// Paper end - per player mob count backoff // Paper end - per player mob count backoff
if (doSpawning == PreSpawnStatus.ABORT) { if (doSpawning == PreSpawnStatus.ABORT) {
@@ -155,7 +155,7 @@ index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070
} }
mobForSpawn.moveTo(d, y, d1, level.random.nextFloat() * 360.0F, 0.0F); mobForSpawn.moveTo(d, y, d1, level.random.nextFloat() * 360.0F, 0.0F);
@@ -324,7 +362,7 @@ public final class NaturalSpawner { @@ -313,7 +351,7 @@ public final class NaturalSpawner {
} }
// CraftBukkit end // CraftBukkit end
if (i >= mobForSpawn.getMaxSpawnClusterSize() || i >= maxSpawns) { // Paper - Optional per player mob spawns if (i >= mobForSpawn.getMaxSpawnClusterSize() || i >= maxSpawns) { // Paper - Optional per player mob spawns
@@ -164,7 +164,7 @@ index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070
} }
if (mobForSpawn.isMaxGroupSizeReached(i3)) { if (mobForSpawn.isMaxGroupSizeReached(i3)) {
@@ -337,6 +375,8 @@ public final class NaturalSpawner { @@ -326,6 +364,8 @@ public final class NaturalSpawner {
} }
} }
} }

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Optimize Raids
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 92e35158b68dcb8d1f34fb1b748c12d1d39468c7..c87d1f81bd1b4b9756bd2f4c1dbc58a2dc85c63b 100644 index 18719b17cfe19b7f864adcec0842da9ab6ee6abb..9ed108791b6e6eb81dfd90b36f054566ce62022f 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -219,6 +219,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -219,6 +219,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe

View File

@@ -0,0 +1,357 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Mon, 24 Feb 2025 19:58:39 +0300
Subject: [PATCH] Regionized Chunk Ticking
This patch adds regionized chunk ticking feature, by grouping adjacent chunks into regions and processing each region on its own thread.
Original idea by Dueris, modified by NONPLAYT and dan28000
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index ae0e36d198ad8243920c8e8a55c0be4945542763..aa515bc07b899351f2b0ac8d61df8e5586616084 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -54,6 +54,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private static final Logger LOGGER = LogUtils.getLogger();
private final DistanceManager distanceManager;
private final ServerLevel level;
+ public static final Executor REGION_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadCount, new org.bxteam.divinemc.util.NamedAgnosticThreadFactory<>("region_ticking", ca.spottedleaf.moonrise.common.util.TickThread::new, org.bxteam.divinemc.DivineConfig.regionizedChunkTickingExecutorThreadPriority)); // DivineMC - Regionized Chunk Ticking
public final Thread mainThread;
final ThreadedLevelLightEngine lightEngine;
public final ServerChunkCache.MainThreadExecutor mainThreadProcessor;
@@ -66,8 +67,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private final long[] lastChunkPos = new long[4];
private final ChunkStatus[] lastChunkStatus = new ChunkStatus[4];
private final ChunkAccess[] lastChunk = new ChunkAccess[4];
- private final List<LevelChunk> tickingChunks = new ArrayList<>();
- private final Set<ChunkHolder> chunkHoldersToBroadcast = new ReferenceOpenHashSet<>();
+ // DivineMC start - Regionized Chunk Ticking
+ private final it.unimi.dsi.fastutil.objects.ObjectArrayList<LevelChunk> tickingChunks = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
+ private final Set<ChunkHolder> chunkHoldersToBroadcast = java.util.Collections.synchronizedSet(new ReferenceOpenHashSet<>());
+ // DivineMC end - Regionized Chunk Ticking
@Nullable
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
@@ -80,6 +83,92 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
// Paper end
// Paper start - rewrite chunk system
+ // DivineMC start - Regionized Chunk Ticking
+ private record RegionData(List<LevelChunk> chunks, List<Entity> entities) {
+ public boolean isEmpty() {
+ return chunks.isEmpty();
+ }
+ }
+
+ private static final int[] DX = {1, -1, 0, 0, 1, -1, -1, 1};
+ private static final int[] DZ = {0, 0, 1, -1, 1, 1, -1, -1};
+
+ private RegionData[] splitChunksIntoRegions(List<LevelChunk> chunks) {
+ if (chunks.isEmpty()) return new RegionData[0];
+
+ int size = chunks.size();
+ it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<LevelChunk> chunkSet = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(chunks);
+
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<RegionData> groups = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(Math.max(1, level.players.size()));
+ LevelChunk[] stack = new LevelChunk[size];
+ it.unimi.dsi.fastutil.longs.Long2IntMap chunkToRegionMap = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(size);
+
+ for (LevelChunk chunk : chunks) {
+ if (!chunkSet.contains(chunk)) continue;
+
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<LevelChunk> group = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(64);
+ stack[0] = chunk;
+ int stackPointer = 1;
+ chunkSet.remove(chunk);
+
+ while (stackPointer > 0) {
+ LevelChunk current = stack[--stackPointer];
+ group.add(current);
+
+ for (int i = 0; i < 8; i++) {
+ LevelChunk neighbor = getChunk(current.locX + DX[i], current.locZ + DZ[i], false);
+ if (neighbor != null && chunkSet.remove(neighbor)) {
+ stack[stackPointer++] = neighbor;
+ }
+ }
+ }
+
+ RegionData regionData = new RegionData(group, new it.unimi.dsi.fastutil.objects.ObjectArrayList<>());
+ groups.add(regionData);
+ int index = groups.indexOf(regionData);
+
+ for (LevelChunk regionChunk : group) {
+ chunkToRegionMap.put(regionChunk.coordinateKey, index);
+ }
+
+ if (chunkSet.isEmpty()) break;
+ }
+
+ level.entityTickList.entities.forEach(entity -> {
+ long chunkKey = entity.chunkPosition().longKey;
+
+ int index = chunkToRegionMap.get(chunkKey);
+ RegionData regionData = groups.get(index);
+ if (regionData != null) {
+ regionData.entities().add(entity);
+ } else {
+ tickEntity(entity);
+ }
+ });
+
+ return groups.toArray(new RegionData[0]);
+ }
+
+ private void tickEntity(Entity entity) {
+ if (!entity.isRemoved()) {
+ if (!level.tickRateManager().isEntityFrozen(entity)) {
+ entity.checkDespawn();
+ // Paper - rewrite chunk system
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ if (!vehicle.isRemoved() && vehicle.hasPassenger(entity)) {
+ return;
+ }
+
+ entity.stopRiding();
+ }
+
+ level.guardEntityTick(level::tickNonPassenger, entity);
+ }
+ }
+ }
+ // DivineMC end - Regionized Chunk Ticking
+
@Override
public final void moonrise$setFullChunk(final int chunkX, final int chunkZ, final LevelChunk chunk) {
final long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ);
@@ -478,39 +567,106 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
this.clearCache();
}
+ // DivineMC start - Regionized Chunk Ticking
private void tickChunks() {
- long gameTime = this.level.getGameTime();
- long l = gameTime - this.lastInhabitedUpdate;
+ final long gameTime = this.level.getGameTime();
+ final long l = gameTime - this.lastInhabitedUpdate;
this.lastInhabitedUpdate = gameTime;
- if (!this.level.isDebug()) {
- if (this.level.tickRateManager().runsNormally()) {
- List<LevelChunk> list = this.tickingChunks;
-
- try {
- this.collectTickingChunks(list);
- // Paper start - chunk tick iteration optimisation
- this.shuffleRandom.setSeed(this.level.random.nextLong());
- if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
- // Paper end - chunk tick iteration optimisation
- this.tickChunks(l, list);
- } finally {
- list.clear();
- }
- }
+ if (this.level.isDebug()) return;
+
+ if (!this.level.tickRateManager().runsNormally()) {
this.broadcastChangedChunks();
+ return;
+ }
+
+ final it.unimi.dsi.fastutil.objects.ObjectArrayList<LevelChunk> list = this.tickingChunks;
+
+ try {
+ this.collectTickingChunks(list);
+
+ if (list.isEmpty()) return;
+
+ // Paper start - chunk tick iteration optimisation
+ this.shuffleRandom.setSeed(this.level.random.nextLong());
+
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ }
+ // Paper end - chunk tick iteration optimisation
+
+ if (org.bxteam.divinemc.DivineConfig.enableRegionizedChunkTicking) {
+ this.processChunksRegionized(l, list);
+ } else {
+ this.tickChunks(l, list);
+ this.broadcastChangedChunks();
+ }
+ } finally {
+ list.clear();
}
}
+ private void processChunksRegionized(final long timeDelta, final List<LevelChunk> chunks) {
+ final RegionData[] regions = splitChunksIntoRegions(chunks);
+ final int regionCount = regions.length;
+
+ if (regionCount == 0) return;
+
+ java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(regionCount);
+
+ try {
+ io.papermc.paper.entity.activation.ActivationRange.activateEntities(level);
+ java.util.concurrent.ForkJoinPool.managedBlock(new java.util.concurrent.ForkJoinPool.ManagedBlocker() {
+ @Override
+ public boolean block() throws InterruptedException {
+ for (final RegionData region : regions) {
+ if (region == null || region.isEmpty()) {
+ latch.countDown();
+ continue;
+ }
+
+ REGION_EXECUTOR.execute(() -> {
+ try {
+ tickChunks(timeDelta, region.chunks());
+
+ for (Entity entity : region.entities()) {
+ tickEntity(entity);
+ }
+ } finally {
+ latch.countDown();
+ }
+ });
+ }
+ broadcastChangedChunks();
+
+ latch.await();
+ return true;
+ }
+
+ @Override
+ public boolean isReleasable() {
+ return latch.getCount() == 0;
+ }
+ });
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("Interrupted managed block during region ticking", ex);
+ }
+ }
+ // DivineMC end - Regionized Chunk Ticking
+
private void broadcastChangedChunks() {
- for (ChunkHolder chunkHolder : this.chunkHoldersToBroadcast) {
- LevelChunk tickingChunk = chunkHolder.getChunkToSend(); // Paper - rewrite chunk system
- if (tickingChunk != null) {
- chunkHolder.broadcastChanges(tickingChunk);
+ // DivineMC start - Regionized Chunk Ticking
+ synchronized (chunkHoldersToBroadcast) {
+ for (ChunkHolder chunkHolder : this.chunkHoldersToBroadcast) {
+ LevelChunk tickingChunk = chunkHolder.getChunkToSend(); // Paper - rewrite chunk system
+ if (tickingChunk != null) {
+ chunkHolder.broadcastChanges(tickingChunk);
+ }
}
- }
- this.chunkHoldersToBroadcast.clear();
+ this.chunkHoldersToBroadcast.clear();
+ }
+ // DivineMC end - Regionized Chunk Ticking
}
private void collectTickingChunks(List<LevelChunk> output) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 9ed108791b6e6eb81dfd90b36f054566ce62022f..a21924072632d8195d803b372058c2557d6428b2 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -193,7 +193,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private final LevelTicks<Block> blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded);
private final LevelTicks<Fluid> fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded);
private final PathTypeCache pathTypesByPosCache = new PathTypeCache();
- final Set<Mob> navigatingMobs = new ObjectOpenHashSet<>();
+ final Set<Mob> navigatingMobs = java.util.Collections.synchronizedSet(new ObjectOpenHashSet<>()); // DivineMC - Regionized Chunk Ticking
volatile boolean isUpdatingNavigations;
protected final Raids raids;
private final ObjectLinkedOpenHashSet<BlockEventData> blockEvents = new ObjectLinkedOpenHashSet<>();
@@ -816,6 +816,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.dragonFight.tick();
}
+ if (org.bxteam.divinemc.DivineConfig.enableRegionizedChunkTicking) {
+ this.tickBlockEntities();
+ return;
+ }
+
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
this.entityTickList
.forEach(
@@ -1793,22 +1798,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) {
List<PathNavigation> list = new ObjectArrayList<>();
- try { // Paper - catch CME see below why
- for (Mob mob : this.navigatingMobs) {
- PathNavigation navigation = mob.getNavigation();
- if (navigation.shouldRecomputePath(pos)) {
- list.add(navigation);
+ // DivineMC start - Regionized Chunk Ticking
+ synchronized (this.navigatingMobs) {
+ for (Mob mob : this.navigatingMobs) {
+ PathNavigation navigation = mob.getNavigation();
+ if (navigation.shouldRecomputePath(pos)) {
+ list.add(navigation);
+ }
}
}
- // Paper start - catch CME see below why
- } catch (final java.util.ConcurrentModificationException concurrentModificationException) {
- // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register
- // In this case we just run the update again across all the iterators as the chunk will then be loaded
- // As this is a relative edge case it is much faster than copying navigators (on either read or write)
- this.sendBlockUpdated(pos, oldState, newState, flags);
- return;
- }
- // Paper end - catch CME see below why
+ // DivineMC end - Regionized Chunk Ticking
try {
this.isUpdatingNavigations = true;
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 502473920a8dec1fcd3321d863f07c977b3643f2..f420cf116ca010f00a41df2f28fc8d9c658fc1f3 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -115,7 +115,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public static final int MIN_ENTITY_SPAWN_Y = -20000000;
public final org.bxteam.divinemc.util.BlockEntityTickersList blockEntityTickers = new org.bxteam.divinemc.util.BlockEntityTickersList(); // Paper - public // DivineMC - optimize block entity removals - Fix MC-117075
protected final NeighborUpdater neighborUpdater;
- private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
+ private final List<TickingBlockEntity> pendingBlockEntityTickers = java.util.Collections.synchronizedList(Lists.newArrayList()); // DivineMC - Regionized Chunk Ticking
private boolean tickingBlockEntities;
public final Thread thread;
private final boolean isDebug;
@@ -148,7 +148,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public boolean isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
- public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
+ public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = java.util.Collections.synchronizedMap(new java.util.LinkedHashMap<>()); // Paper // DivineMC - Regionized Chunk Ticking
public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates
public List<net.minecraft.world.entity.item.ItemEntity> captureDrops;
public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
diff --git a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
index 028eae2f9a459b60e92f3344091083aa93b54485..51e5a54aff069cac14deef6c04899d3a469842ce 100644
--- a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java
@@ -46,7 +46,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
this.addAndRun(pos, new CollectingNeighborUpdater.MultiNeighborUpdate(pos.immutable(), block, orientation, facing));
}
- private void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates updates) {
+ private synchronized void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates updates) { // DivineMC - Regionized Chunk Ticking - synchronized
boolean flag = this.count > 0;
boolean flag1 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates;
this.count++;
@@ -65,7 +65,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater {
}
}
- private void runUpdates() {
+ private synchronized void runUpdates() { // DivineMC - Regionized Chunk Ticking - synchronized
try {
while (!this.stack.isEmpty() || !this.addedThisLayer.isEmpty()) {
for (int i = this.addedThisLayer.size() - 1; i >= 0; i--) {

View File

@@ -17,10 +17,10 @@ index 51b79f614417f231951e9ba05b29ff0044e081e7..dee93ae262a2a06e68dfe8ae1b719317
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) { public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f7c17a7db 100644 index aa515bc07b899351f2b0ac8d61df8e5586616084..83157183ab2363eebd8a19d1e018b6bd5c736507 100644
--- a/net/minecraft/server/level/ServerChunkCache.java --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -183,6 +183,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -268,6 +268,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
} }
// Paper end - chunk tick iteration optimisations // Paper end - chunk tick iteration optimisations
@@ -31,9 +31,9 @@ index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f
public ServerChunkCache( public ServerChunkCache(
ServerLevel level, ServerLevel level,
@@ -581,6 +585,35 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -651,6 +655,35 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
} catch (InterruptedException ex) {
this.broadcastChangedChunks(); throw new RuntimeException("Interrupted managed block during region ticking", ex);
} }
+ +
+ // DivineMC start - Async mob spawning + // DivineMC start - Async mob spawning
@@ -65,9 +65,9 @@ index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f
+ } + }
+ // DivineMC end - Async mob spawning + // DivineMC end - Async mob spawning
} }
// DivineMC end - Regionized Chunk Ticking
private void broadcastChangedChunks() { @@ -696,27 +729,31 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -621,27 +654,31 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount(); int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
// Paper start - Optional per player mob spawns // Paper start - Optional per player mob spawns
NaturalSpawner.SpawnState spawnState; NaturalSpawner.SpawnState spawnState;
@@ -113,7 +113,7 @@ index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
List<MobCategory> filteredSpawningCategories; List<MobCategory> filteredSpawningCategories;
@@ -655,7 +692,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -730,7 +767,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
} }
// Paper end - PlayerNaturallySpawnCreaturesEvent // Paper end - PlayerNaturallySpawnCreaturesEvent
boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
@@ -122,7 +122,7 @@ index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f
} else { } else {
filteredSpawningCategories = List.of(); filteredSpawningCategories = List.of();
} }
@@ -663,8 +700,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -738,8 +775,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
for (LevelChunk levelChunk : chunks) { for (LevelChunk levelChunk : chunks) {
ChunkPos pos = levelChunk.getPos(); ChunkPos pos = levelChunk.getPos();
levelChunk.incrementInhabitedTime(timeInhabited); levelChunk.incrementInhabitedTime(timeInhabited);
@@ -136,7 +136,7 @@ index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f
if (true) { // Paper - rewrite chunk system if (true) { // Paper - rewrite chunk system
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index d3f5242fc66529bf3137da4d505a6cf55e749e43..650dfce05bfc68d4c664471b430bd5c0f9629283 100644 index 1056a17c53e7d16d5fba7f9a354dfbc235d4d974..3e9ab446632ffe56de45f7622db44070e1cbaf1f 100644
--- a/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -155,7 +155,18 @@ public final class NaturalSpawner { @@ -155,7 +155,18 @@ public final class NaturalSpawner {
@@ -158,7 +158,7 @@ index d3f5242fc66529bf3137da4d505a6cf55e749e43..650dfce05bfc68d4c664471b430bd5c0
for (MobCategory mobCategory : categories) { for (MobCategory mobCategory : categories) {
// Paper start - Optional per player mob spawns // Paper start - Optional per player mob spawns
final boolean canSpawn; final boolean canSpawn;
@@ -642,6 +653,13 @@ public final class NaturalSpawner { @@ -682,6 +693,13 @@ public final class NaturalSpawner {
} }
boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) { boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) {

View File

@@ -30,11 +30,23 @@ index ae0a3c3d9d6300293a6d0dff5cae49ebe7c11dab..3b08dad7a9fac7ac9acec0bfb85d4826
} }
} }
} }
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 83157183ab2363eebd8a19d1e018b6bd5c736507..4377b6712c8990f9bd444d662414b68ab9d92963 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -150,6 +150,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
}
private void tickEntity(Entity entity) {
+ entity.activatedPriorityReset = false; // DivineMC - Dynamic Activation of Brain
if (!entity.isRemoved()) {
if (!level.tickRateManager().isEntityFrozen(entity)) {
entity.checkDespawn();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 561066a2cf769e13ef3cea0881f7a2010ecbf2ec..5fe908ce51f95e1eab024dcd41ed108373f17fea 100644 index a21924072632d8195d803b372058c2557d6428b2..b50f8ff69157c07b509e88c65fb217d3dde73f1e 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -818,6 +818,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -825,6 +825,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.entityTickList this.entityTickList
.forEach( .forEach(
entity -> { entity -> {
@@ -43,7 +55,7 @@ index 561066a2cf769e13ef3cea0881f7a2010ecbf2ec..5fe908ce51f95e1eab024dcd41ed1083
if (!tickRateManager.isEntityFrozen(entity)) { if (!tickRateManager.isEntityFrozen(entity)) {
entity.checkDespawn(); entity.checkDespawn();
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 04ae7636d14a40a427b5d9b746632b0c489efa21..f1cd66d7d96771bc4967e214f70c756fec30efe5 100644 index 07e8bda8eb200d5a7554e0319e1a00dc85454e1a..ed8c715f4a24188e43769fa04af8e71e1573c041 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -336,6 +336,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -336,6 +336,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -414,7 +426,7 @@ index 59a12809e5c7f5ee85ca1f587f6b77383a1ff062..9777f5e99909790b49b05ea64fe12ded
@Override @Override
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
index fec90e482c8935dfca609bbf90e67f86a1586221..2ac8a11e9afc6f776eba3dbe852d7b680ed21705 100644 index 4ee1791f293ba3abdbfe69824b85566fd9a36586..2a4b5821d352f828e3c955a6ffa0bfdf6ff6911a 100644
--- a/net/minecraft/world/entity/npc/Villager.java --- a/net/minecraft/world/entity/npc/Villager.java
+++ b/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java
@@ -179,6 +179,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -179,6 +179,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler

View File

@@ -18,10 +18,10 @@ index 34682217252cb98a70511a8cb25f077ec9f872b8..eccd330a332a927354f47acd16295c23
this.scheduleReadIO(); this.scheduleReadIO();
return; return;
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index bea62fca118efdd6257188cd53c813dc5fd0c19c..adca106b1100b5c5236f40eb3795ac89c1fa0288 100644 index b50f8ff69157c07b509e88c65fb217d3dde73f1e..9e0d482065bd6434128cd653c3580b633ed7202d 100644
--- a/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -1403,7 +1403,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1408,7 +1408,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
} }
if (doFull) { if (doFull) {

View File

@@ -95,4 +95,11 @@ public final class BlockEntityTickersList extends ObjectArrayList<TickingBlockEn
Arrays.fill(a, j, size, null); Arrays.fill(a, j, size, null);
size = j; size = j;
} }
@Override
public boolean addAll(int index, final Collection<? extends TickingBlockEntity> c) {
synchronized (c) {
return super.addAll(index, c);
}
}
} }