From 14c80ea6ebdbe68b0bc9d5897890db9fa75f5dfa Mon Sep 17 00:00:00 2001 From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> Date: Fri, 31 Oct 2025 19:49:24 +0300 Subject: [PATCH] [ci-skip] reformat patches --- .../0050-Catch-update-suppressors.patch | 379 ----------- .../0051-Regionized-Chunk-Ticking.patch | 386 +++++++++++ ....patch => 0052-C2ME-Limit-NBT-cache.patch} | 0 ...2ME-Optimize-Aquifer-and-Beardifier.patch} | 0 ...patch => 0054-Copper-Bulb-1gt-delay.patch} | 0 ...lay.patch => 0055-Crafter-1gt-delay.patch} | 0 ...tch => 0056-Raytrace-Entity-Tracker.patch} | 0 ....patch => 0057-Leaves-Protocol-Core.patch} | 0 ...R-Optimise-non-flush-packet-sending.patch} | 0 ...h => 0059-Linear-region-file-format.patch} | 0 ...> 0060-Cleanup-dead-code-from-Paper.patch} | 0 ...ch => 0061-C2ME-The-End-Biome-Cache.patch} | 0 ...2-Euclidean-distance-squared-option.patch} | 0 ...Do-not-send-spectator-change-packet.patch} | 0 ...verListPingEvent-for-secondary-motd.patch} | 0 ...gurable-player-spawn-tracking-range.patch} | 0 ....patch => 0066-Optimize-collections.patch} | 0 ...atch => 0067-Optimize-level-ticking.patch} | 0 ...ise.patch => 0068-Optimize-Moonrise.patch} | 4 +- ...9-lithium-combined_heightmap_update.patch} | 0 ...ck.patch => 0070-Entity-Status-Lock.patch} | 0 ... 0071-lithium-sleeping_block_entity.patch} | 0 ... => 0072-lithium-equipment_tracking.patch} | 0 ...> 0073-Configurable-Files-Locations.patch} | 0 ...Cache-climbing-check-for-activation.patch} | 0 ...ntityCollisionContext-a-live-repres.patch} | 0 ...r-checking-for-useless-move-packets.patch} | 0 .../paper-patches/features/0001-Rebrand.patch | 625 +++++++++--------- 28 files changed, 708 insertions(+), 686 deletions(-) create mode 100644 divinemc-server/minecraft-patches/features/0051-Regionized-Chunk-Ticking.patch rename divinemc-server/minecraft-patches/features/{0051-C2ME-Limit-NBT-cache.patch => 0052-C2ME-Limit-NBT-cache.patch} (100%) rename divinemc-server/minecraft-patches/features/{0052-C2ME-Optimize-Aquifer-and-Beardifier.patch => 0053-C2ME-Optimize-Aquifer-and-Beardifier.patch} (100%) rename divinemc-server/minecraft-patches/features/{0053-Copper-Bulb-1gt-delay.patch => 0054-Copper-Bulb-1gt-delay.patch} (100%) rename divinemc-server/minecraft-patches/features/{0054-Crafter-1gt-delay.patch => 0055-Crafter-1gt-delay.patch} (100%) rename divinemc-server/minecraft-patches/features/{0055-Raytrace-Entity-Tracker.patch => 0056-Raytrace-Entity-Tracker.patch} (100%) rename divinemc-server/minecraft-patches/features/{0056-Leaves-Protocol-Core.patch => 0057-Leaves-Protocol-Core.patch} (100%) rename divinemc-server/minecraft-patches/features/{0057-Paper-PR-Optimise-non-flush-packet-sending.patch => 0058-Paper-PR-Optimise-non-flush-packet-sending.patch} (100%) rename divinemc-server/minecraft-patches/features/{0058-Linear-region-file-format.patch => 0059-Linear-region-file-format.patch} (100%) rename divinemc-server/minecraft-patches/features/{0059-Cleanup-dead-code-from-Paper.patch => 0060-Cleanup-dead-code-from-Paper.patch} (100%) rename divinemc-server/minecraft-patches/features/{0060-C2ME-The-End-Biome-Cache.patch => 0061-C2ME-The-End-Biome-Cache.patch} (100%) rename divinemc-server/minecraft-patches/features/{0061-Euclidean-distance-squared-option.patch => 0062-Euclidean-distance-squared-option.patch} (100%) rename divinemc-server/minecraft-patches/features/{0062-Do-not-send-spectator-change-packet.patch => 0063-Do-not-send-spectator-change-packet.patch} (100%) rename divinemc-server/minecraft-patches/features/{0063-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch => 0064-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch} (100%) rename divinemc-server/minecraft-patches/features/{0064-Configurable-player-spawn-tracking-range.patch => 0065-Configurable-player-spawn-tracking-range.patch} (100%) rename divinemc-server/minecraft-patches/features/{0065-Optimize-collections.patch => 0066-Optimize-collections.patch} (100%) rename divinemc-server/minecraft-patches/features/{0066-Optimize-level-ticking.patch => 0067-Optimize-level-ticking.patch} (100%) rename divinemc-server/minecraft-patches/features/{0067-Optimize-Moonrise.patch => 0068-Optimize-Moonrise.patch} (99%) rename divinemc-server/minecraft-patches/features/{0068-lithium-combined_heightmap_update.patch => 0069-lithium-combined_heightmap_update.patch} (100%) rename divinemc-server/minecraft-patches/features/{0069-Entity-Status-Lock.patch => 0070-Entity-Status-Lock.patch} (100%) rename divinemc-server/minecraft-patches/features/{0070-lithium-sleeping_block_entity.patch => 0071-lithium-sleeping_block_entity.patch} (100%) rename divinemc-server/minecraft-patches/features/{0071-lithium-equipment_tracking.patch => 0072-lithium-equipment_tracking.patch} (100%) rename divinemc-server/minecraft-patches/features/{0072-Configurable-Files-Locations.patch => 0073-Configurable-Files-Locations.patch} (100%) rename divinemc-server/minecraft-patches/features/{0073-Pufferfish-Cache-climbing-check-for-activation.patch => 0074-Pufferfish-Cache-climbing-check-for-activation.patch} (100%) rename divinemc-server/minecraft-patches/features/{0074-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch => 0075-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch} (100%) rename divinemc-server/minecraft-patches/features/{0075-Pufferfish-Better-checking-for-useless-move-packets.patch => 0076-Pufferfish-Better-checking-for-useless-move-packets.patch} (100%) diff --git a/divinemc-server/minecraft-patches/features/0050-Catch-update-suppressors.patch b/divinemc-server/minecraft-patches/features/0050-Catch-update-suppressors.patch index 6ef3439..845cbba 100644 --- a/divinemc-server/minecraft-patches/features/0050-Catch-update-suppressors.patch +++ b/divinemc-server/minecraft-patches/features/0050-Catch-update-suppressors.patch @@ -4,19 +4,6 @@ Date: Sun, 23 Feb 2025 01:14:54 +0300 Subject: [PATCH] Catch update suppressors -diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index 35b6f8365f4568da7bc0f4e47c39cb3690292aaf..e28d859b457ca0e24bc6dc9d6cd4a97f12ae0671 100644 ---- a/net/minecraft/network/Connection.java -+++ b/net/minecraft/network/Connection.java -@@ -327,7 +327,7 @@ public class Connection extends SimpleChannelInboundHandler> { - - private static void syncAfterConfigurationChange(ChannelFuture future) { - try { -- future.syncUninterruptibly(); -+ future.awaitUninterruptibly(5000L); // DivineMC - In rare cases this can get stuck, so we time out instead in worst case 5s of lag - } catch (Exception var2) { - if (var2 instanceof ClosedChannelException) { - LOGGER.info("Connection closed during protocol change"); diff --git a/net/minecraft/network/PacketProcessor.java b/net/minecraft/network/PacketProcessor.java index 3e4241976fdfe65bc0aae90a9097770745c0ddf1..98b101fde04fbf5507f021bb8d8e6bed334de5b6 100644 --- a/net/minecraft/network/PacketProcessor.java @@ -47,350 +34,6 @@ index e3c7065cd4832e0c533f70d444c0a7beff53e423..d73546a9f086f67bafb3ce3a2a8ed5c2 } catch (Throwable levelTickingException) { CrashReport crashReport = CrashReport.forThrowable(levelTickingException, "Exception ticking world"); serverLevel.fillReportDetails(crashReport); -diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 04dd1bec1aff470e67a21fb0b25932685992ec82..72a0a80f1fffa43e143c80c689db5302f462114e 100644 ---- a/net/minecraft/server/level/ChunkMap.java -+++ b/net/minecraft/server/level/ChunkMap.java -@@ -737,7 +737,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise chunk tick iteration - final ca.spottedleaf.moonrise.common.list.ReferenceList tickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks(); - -- final LevelChunk[] raw = tickingChunks.getRawDataUnchecked(); -+ final LevelChunk[] raw = tickingChunks.toArray(new LevelChunk[0]); // DivineMC - Regionized Chunk Ticking - sync fix - final int size = tickingChunks.size(); - - Objects.checkFromToIndex(0, size, raw.length); -diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 6ea62fbffda38e477ef8e119608fc93793db95c3..74f63e549f8cadc80de26fcad11923151e0c40eb 100644 ---- a/net/minecraft/server/level/ServerChunkCache.java -+++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -57,7 +57,7 @@ import org.slf4j.Logger; - public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache { // Paper - rewrite chunk system - private static final Logger LOGGER = LogUtils.getLogger(); - private final DistanceManager distanceManager; -- private final ServerLevel level; -+ protected final ServerLevel level; // DivineMC - Regionized Chunk Ticking - private -> protected - public final Thread mainThread; - final ThreadedLevelLightEngine lightEngine; - public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; -@@ -71,8 +71,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 spawningChunks = new ObjectArrayList<>(); -- private final Set chunkHoldersToBroadcast = new ReferenceOpenHashSet<>(); -+ // DivineMC start - Regionized Chunk Ticking -+ private final ObjectArrayList spawningChunks = new ObjectArrayList<>(); -+ private final Set chunkHoldersToBroadcast = java.util.Collections.synchronizedSet(new ReferenceOpenHashSet<>()); -+ // DivineMC end - Regionized Chunk Ticking - @Nullable - @VisibleForDebug - private NaturalSpawner.SpawnState lastSpawnState; -@@ -156,34 +158,47 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Paper end - rewrite chunk system - // Paper start - chunk tick iteration optimisations - private final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom shuffleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(0L); -- private void iterateTickingChunksFaster() { -+ private void iterateTickingChunksFaster(final CompletableFuture spawns) { // DivineMC - Regionized Chunk Ticking - final ServerLevel world = this.level; - final int randomTickSpeed = world.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); - - // TODO check on update: impl of forEachBlockTickingChunk will only iterate ENTITY ticking chunks! - // TODO check on update: consumer just runs tickChunk -- final ca.spottedleaf.moonrise.common.list.ReferenceList entityTickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks(); -+ final ca.spottedleaf.moonrise.common.list.ReferenceList entityTickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks(); // DivineMC - Regionized Chunk Ticking - - // note: we can use the backing array here because: - // 1. we do not care about new additions - // 2. _removes_ are impossible at this stage in the tick -- final LevelChunk[] raw = entityTickingChunks.getRawDataUnchecked(); -+ final LevelChunk[] raw = entityTickingChunks.toArray(new LevelChunk[0]); // DivineMC - use toArray instead of getRawDataUnchecked this way is safe and doesn't have performance impact - final int size = entityTickingChunks.size(); - -- java.util.Objects.checkFromToIndex(0, size, raw.length); -- for (int i = 0; i < size; ++i) { -- world.tickChunk(raw[i], randomTickSpeed); -- -- // call mid-tick tasks for chunk system -- if ((i & 7) == 0) { -- // DivineMC start - Parallel world ticking -- if (!org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) { -- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer) this.level.getServer()).moonrise$executeMidTickTasks(); -- continue; -- } -+ // DivineMC start - Regionized Chunk Ticking -+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { -+ if (this instanceof org.bxteam.divinemc.async.rct.RegionizedChunkTicking rct) { -+ rct.execute(spawns, raw); -+ } -+ } else { -+ java.util.Objects.checkFromToIndex(0, size, raw.length); -+ for (int i = 0; i < size; ++i) { -+ world.tickChunk(raw[i], randomTickSpeed); -+ -+ // call mid-tick tasks for chunk system -+ if ((i & 7) == 0) { -+ // DivineMC start - Parallel world ticking -+ if (!org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) { -+ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer) this.level.getServer()).moonrise$executeMidTickTasks(); -+ continue; -+ } -+ // DivineMC end - Parallel world ticking -+ } - // DivineMC end - Parallel world ticking - } -- } -+ -+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.asyncNaturalSpawn) { -+ spawns.join(); -+ } -+ } -+ // DivineMC end - Regionized Chunk Ticking - } - // Paper end - chunk tick iteration optimisations - -@@ -502,14 +517,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - long gameTime = this.level.getGameTime(); - long l = gameTime - this.lastInhabitedUpdate; - this.lastInhabitedUpdate = gameTime; -- if (!this.level.isDebug()) { -- if (this.level.tickRateManager().runsNormally()) { -- this.tickChunks(l); -- } - -+ // DivineMC start - Regionized Chunk Ticking -+ if (this.level.isDebug()) { -+ return; -+ } -+ -+ if (!this.level.tickRateManager().runsNormally()) { // DivineMC - when frozen only broadcast changed chunks and don't run async mob spawning - this.broadcastChangedChunks(); -+ return; - } - -+ this.tickChunks(l); -+ this.broadcastChangedChunks(); -+ // DivineMC end - Regionized Chunk Ticking -+ - // DivineMC start - Pufferfish: Optimize mob spawning - if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableAsyncSpawning) { - for (ServerPlayer player : this.level.players) { -@@ -553,14 +575,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - - 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 tickChunks(long timeInhabited) { -@@ -610,6 +636,24 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - filteredSpawningCategories = List.of(); - } - -+ // DivineMC start - Regionized Chunk Ticking -+ final CompletableFuture spawns; -+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.asyncNaturalSpawn) { -+ spawns = CompletableFuture.runAsync(() -> naturalSpawn(filteredSpawningCategories, timeInhabited), org.bxteam.divinemc.async.rct.RegionizedChunkTicking.REGION_EXECUTOR); -+ } else { -+ naturalSpawn(filteredSpawningCategories, timeInhabited); -+ spawns = new CompletableFuture<>(); -+ } -+ // DivineMC end - Regionized Chunk Ticking -+ -+ this.iterateTickingChunksFaster(spawns); // Paper - chunk tick iteration optimisations // DivineMC - Regionized Chunk Ticking -+ if (_boolean) { -+ this.level.tickCustomSpawners(this.spawnEnemies); -+ } -+ } -+ -+ // DivineMC start - Regionized Chunk Ticking -+ private void naturalSpawn(List filteredSpawningCategories, long timeInhabited) { - List list = this.spawningChunks; - - try { -@@ -627,12 +671,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } finally { - list.clear(); - } -+ } - -- this.iterateTickingChunksFaster(); // Paper - chunk tick iteration optimisations -- if (_boolean) { -- this.level.tickCustomSpawners(this.spawnEnemies); -- } -+ protected net.minecraft.world.level.entity.EntityTickList getEntityTickList() { -+ return level.entityTickList; - } -+ // DivineMC end - Regionized Chunk Ticking - - private void tickSpawningChunk(LevelChunk chunk, long timeInhabited, List spawnCategories, NaturalSpawner.SpawnState spawnState) { - ChunkPos pos = chunk.getPos(); -diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index ca9883277c0f036c94e861f7917ca42facd3c47b..8c98c2593eec14a8a378041e94cf52b8fbfedc30 100644 ---- a/net/minecraft/server/level/ServerLevel.java -+++ b/net/minecraft/server/level/ServerLevel.java -@@ -197,7 +197,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - private final LevelTicks blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); - private final LevelTicks fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); - private final PathTypeCache pathTypesByPosCache = new PathTypeCache(); -- final Set navigatingMobs = new ObjectOpenHashSet<>(); -+ final Set navigatingMobs = java.util.Collections.synchronizedSet(new ObjectOpenHashSet<>()); // DivineMC - Regionized Chunk Ticking - volatile boolean isUpdatingNavigations; - protected final Raids raids; - private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>(); -@@ -666,19 +666,37 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - boolean flag = server.forceSynchronousWrites(); - DataFixer fixerUpper = server.getFixerUpper(); - // Paper - rewrite chunk system -- this.chunkSource = new ServerChunkCache( -- this, -- levelStorageAccess, -- fixerUpper, -- server.getStructureManager(), -- dispatcher, -- chunkGenerator, -- this.spigotConfig.viewDistance, // Spigot -- this.spigotConfig.simulationDistance, // Spigot -- flag, -- null, // Paper - rewrite chunk system -- () -> server.overworld().getDataStorage() -- ); -+ // DivineMC start - Regionized Chunk Ticking -+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { -+ this.chunkSource = new org.bxteam.divinemc.async.rct.RegionizedChunkTicking( -+ this, -+ levelStorageAccess, -+ fixerUpper, -+ server.getStructureManager(), -+ dispatcher, -+ chunkGenerator, -+ this.spigotConfig.viewDistance, // Spigot -+ this.spigotConfig.simulationDistance, // Spigot -+ flag, -+ null, // Paper - rewrite chunk system -+ () -> server.overworld().getDataStorage() -+ ); -+ } else { -+ this.chunkSource = new ServerChunkCache( -+ this, -+ levelStorageAccess, -+ fixerUpper, -+ server.getStructureManager(), -+ dispatcher, -+ chunkGenerator, -+ this.spigotConfig.viewDistance, // Spigot -+ this.spigotConfig.simulationDistance, // Spigot -+ flag, -+ null, // Paper - rewrite chunk system -+ () -> server.overworld().getDataStorage() -+ ); -+ } -+ // DivineMC end - Regionized Chunk Ticking - this.chunkSource.getGeneratorState().ensureStructuresGenerated(); - this.portalForcer = new PortalForcer(this); - this.updateSkyBrightness(); -@@ -846,6 +864,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - this.dragonFight.tick(); - } - -+ // DivineMC start - Regionized Chunk Ticking -+ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { -+ this.tickBlockEntities(); -+ return; -+ } -+ // DivineMC end - Regionized Chunk Ticking -+ - io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR - this.entityTickList - .forEach( -@@ -1874,22 +1899,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) { - List 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 7fe5cb2ea1c81b12baf302999a2794f20018707c..738cbde3595165e0f05c0a6fde21499e98dc850b 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -113,7 +113,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - .build(); - public final org.bxteam.divinemc.util.BlockEntityTickersList blockEntityTickers = new org.bxteam.divinemc.util.BlockEntityTickersList(); // DivineMC - optimize block entity removals - Fix MC-117075 - protected final CollectingNeighborUpdater neighborUpdater; -- private final List pendingBlockEntityTickers = Lists.newArrayList(); -+ private final List pendingBlockEntityTickers = java.util.Collections.synchronizedList(Lists.newArrayList()); // DivineMC - Regionized Chunk Ticking - private boolean tickingBlockEntities; - public final Thread thread; - private final boolean isDebug; -@@ -145,7 +145,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; -- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper -+ public Map capturedBlockStates = java.util.Collections.synchronizedMap(new java.util.LinkedHashMap<>()); // Paper // DivineMC - Regionized Chunk Ticking - public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates - @Nullable - public List captureDrops; -@@ -1459,10 +1459,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - public void tickBlockEntities() { - this.tickingBlockEntities = true; -- if (!this.pendingBlockEntityTickers.isEmpty()) { -- this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); -- this.pendingBlockEntityTickers.clear(); -+ // DivineMC start - Regionized Chunk Ticking - synchronization fix -+ synchronized (pendingBlockEntityTickers) { -+ if (!this.pendingBlockEntityTickers.isEmpty()) { -+ this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); -+ this.pendingBlockEntityTickers.clear(); -+ } - } -+ // DivineMC end - Regionized Chunk Ticking - synchronization fix - - // Spigot start - boolean runsNormally = this.tickRateManager().runsNormally(); diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java index e08083fbb6c3090c9a6f78dbbe487cbd4fec485a..d5d77110e7799223a66c2d6e47a1d9b4653f3ec4 100644 --- a/net/minecraft/world/level/block/ShulkerBoxBlock.java @@ -414,28 +57,6 @@ index e08083fbb6c3090c9a6f78dbbe487cbd4fec485a..d5d77110e7799223a66c2d6e47a1d9b4 } public static Block getBlockByColor(@Nullable DyeColor color) { -diff --git a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -index 5d17213a692016d2f005c7820bf2cf1f42ce411f..ccb2e0c28aeaebbeef15fbb650fa3c2e5c241ceb 100644 ---- a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -+++ b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -@@ -53,7 +53,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++; -@@ -72,7 +72,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--) { diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java index f45cf0136e77ed5a903d033a7b0611e5edc23db9..e5b0cc92a2f9cdb89cd2436f6591531f8ae91d28 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java diff --git a/divinemc-server/minecraft-patches/features/0051-Regionized-Chunk-Ticking.patch b/divinemc-server/minecraft-patches/features/0051-Regionized-Chunk-Ticking.patch new file mode 100644 index 0000000..1b62102 --- /dev/null +++ b/divinemc-server/minecraft-patches/features/0051-Regionized-Chunk-Ticking.patch @@ -0,0 +1,386 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Mon, 9 Jun 2025 13:51:43 +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 heavily optimized by dan28000 + +diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java +index 35b6f8365f4568da7bc0f4e47c39cb3690292aaf..e28d859b457ca0e24bc6dc9d6cd4a97f12ae0671 100644 +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -327,7 +327,7 @@ public class Connection extends SimpleChannelInboundHandler> { + + private static void syncAfterConfigurationChange(ChannelFuture future) { + try { +- future.syncUninterruptibly(); ++ future.awaitUninterruptibly(5000L); // DivineMC - In rare cases this can get stuck, so we time out instead in worst case 5s of lag + } catch (Exception var2) { + if (var2 instanceof ClosedChannelException) { + LOGGER.info("Connection closed during protocol change"); +diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java +index 04dd1bec1aff470e67a21fb0b25932685992ec82..72a0a80f1fffa43e143c80c689db5302f462114e 100644 +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -737,7 +737,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper start - optimise chunk tick iteration + final ca.spottedleaf.moonrise.common.list.ReferenceList tickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks(); + +- final LevelChunk[] raw = tickingChunks.getRawDataUnchecked(); ++ final LevelChunk[] raw = tickingChunks.toArray(new LevelChunk[0]); // DivineMC - Regionized Chunk Ticking - sync fix + final int size = tickingChunks.size(); + + Objects.checkFromToIndex(0, size, raw.length); +diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java +index 6ea62fbffda38e477ef8e119608fc93793db95c3..dda53860397ee52f64209a8d08a7707cfa2f7592 100644 +--- a/net/minecraft/server/level/ServerChunkCache.java ++++ b/net/minecraft/server/level/ServerChunkCache.java +@@ -57,7 +57,7 @@ import org.slf4j.Logger; + public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache { // Paper - rewrite chunk system + private static final Logger LOGGER = LogUtils.getLogger(); + private final DistanceManager distanceManager; +- private final ServerLevel level; ++ protected final ServerLevel level; // DivineMC - Regionized Chunk Ticking - private -> protected + public final Thread mainThread; + final ThreadedLevelLightEngine lightEngine; + public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; +@@ -71,8 +71,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 spawningChunks = new ObjectArrayList<>(); +- private final Set chunkHoldersToBroadcast = new ReferenceOpenHashSet<>(); ++ // DivineMC start - Regionized Chunk Ticking ++ private final ObjectArrayList spawningChunks = new ObjectArrayList<>(); ++ private final Set chunkHoldersToBroadcast = java.util.Collections.synchronizedSet(new ReferenceOpenHashSet<>()); ++ // DivineMC end - Regionized Chunk Ticking + @Nullable + @VisibleForDebug + private NaturalSpawner.SpawnState lastSpawnState; +@@ -156,34 +158,46 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // Paper end - rewrite chunk system + // Paper start - chunk tick iteration optimisations + private final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom shuffleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(0L); +- private void iterateTickingChunksFaster() { ++ private void iterateTickingChunksFaster(final CompletableFuture spawns) { // DivineMC - Regionized Chunk Ticking + final ServerLevel world = this.level; + final int randomTickSpeed = world.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + + // TODO check on update: impl of forEachBlockTickingChunk will only iterate ENTITY ticking chunks! + // TODO check on update: consumer just runs tickChunk +- final ca.spottedleaf.moonrise.common.list.ReferenceList entityTickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks(); ++ final ca.spottedleaf.moonrise.common.list.ReferenceList entityTickingChunks = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks(); // DivineMC - Regionized Chunk Ticking + + // note: we can use the backing array here because: + // 1. we do not care about new additions + // 2. _removes_ are impossible at this stage in the tick +- final LevelChunk[] raw = entityTickingChunks.getRawDataUnchecked(); ++ final LevelChunk[] raw = entityTickingChunks.toArray(new LevelChunk[0]); // DivineMC - use toArray instead of getRawDataUnchecked this way is safe and doesn't have performance impact + final int size = entityTickingChunks.size(); + +- java.util.Objects.checkFromToIndex(0, size, raw.length); +- for (int i = 0; i < size; ++i) { +- world.tickChunk(raw[i], randomTickSpeed); +- +- // call mid-tick tasks for chunk system +- if ((i & 7) == 0) { +- // DivineMC start - Parallel world ticking +- if (!org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) { +- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer) this.level.getServer()).moonrise$executeMidTickTasks(); +- continue; ++ // DivineMC start - Regionized Chunk Ticking ++ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { ++ if (this instanceof org.bxteam.divinemc.async.rct.RegionizedChunkTicking rct) { ++ rct.execute(spawns, raw); ++ } ++ } else { ++ java.util.Objects.checkFromToIndex(0, size, raw.length); ++ for (int i = 0; i < size; ++i) { ++ world.tickChunk(raw[i], randomTickSpeed); ++ ++ // call mid-tick tasks for chunk system ++ if ((i & 7) == 0) { ++ // DivineMC start - Parallel world ticking ++ if (!org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking) { ++ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer) this.level.getServer()).moonrise$executeMidTickTasks(); ++ continue; ++ } ++ // DivineMC end - Parallel world ticking + } +- // DivineMC end - Parallel world ticking ++ } ++ ++ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.asyncNaturalSpawn) { ++ spawns.join(); + } + } ++ // DivineMC end - Regionized Chunk Ticking + } + // Paper end - chunk tick iteration optimisations + +@@ -502,14 +516,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + long gameTime = this.level.getGameTime(); + long l = gameTime - this.lastInhabitedUpdate; + this.lastInhabitedUpdate = gameTime; +- if (!this.level.isDebug()) { +- if (this.level.tickRateManager().runsNormally()) { +- this.tickChunks(l); +- } + ++ // DivineMC start - Regionized Chunk Ticking ++ if (this.level.isDebug()) { ++ return; ++ } ++ ++ if (!this.level.tickRateManager().runsNormally()) { // DivineMC - when frozen only broadcast changed chunks and don't run async mob spawning + this.broadcastChangedChunks(); ++ return; + } + ++ this.tickChunks(l); ++ this.broadcastChangedChunks(); ++ // DivineMC end - Regionized Chunk Ticking ++ + // DivineMC start - Pufferfish: Optimize mob spawning + if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableAsyncSpawning) { + for (ServerPlayer player : this.level.players) { +@@ -553,14 +574,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + + 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 tickChunks(long timeInhabited) { +@@ -610,6 +635,24 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + filteredSpawningCategories = List.of(); + } + ++ // DivineMC start - Regionized Chunk Ticking ++ final CompletableFuture spawns; ++ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.asyncNaturalSpawn) { ++ spawns = CompletableFuture.runAsync(() -> naturalSpawn(filteredSpawningCategories, timeInhabited), org.bxteam.divinemc.async.rct.RegionizedChunkTicking.REGION_EXECUTOR); ++ } else { ++ naturalSpawn(filteredSpawningCategories, timeInhabited); ++ spawns = new CompletableFuture<>(); ++ } ++ // DivineMC end - Regionized Chunk Ticking ++ ++ this.iterateTickingChunksFaster(spawns); // Paper - chunk tick iteration optimisations // DivineMC - Regionized Chunk Ticking ++ if (_boolean) { ++ this.level.tickCustomSpawners(this.spawnEnemies); ++ } ++ } ++ ++ // DivineMC start - Regionized Chunk Ticking ++ private void naturalSpawn(List filteredSpawningCategories, long timeInhabited) { + List list = this.spawningChunks; + + try { +@@ -627,12 +670,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } finally { + list.clear(); + } ++ } + +- this.iterateTickingChunksFaster(); // Paper - chunk tick iteration optimisations +- if (_boolean) { +- this.level.tickCustomSpawners(this.spawnEnemies); +- } ++ protected net.minecraft.world.level.entity.EntityTickList getEntityTickList() { ++ return level.entityTickList; + } ++ // DivineMC end - Regionized Chunk Ticking + + private void tickSpawningChunk(LevelChunk chunk, long timeInhabited, List spawnCategories, NaturalSpawner.SpawnState spawnState) { + ChunkPos pos = chunk.getPos(); +diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java +index ca9883277c0f036c94e861f7917ca42facd3c47b..8c98c2593eec14a8a378041e94cf52b8fbfedc30 100644 +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -197,7 +197,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + private final LevelTicks blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); + private final LevelTicks fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); + private final PathTypeCache pathTypesByPosCache = new PathTypeCache(); +- final Set navigatingMobs = new ObjectOpenHashSet<>(); ++ final Set navigatingMobs = java.util.Collections.synchronizedSet(new ObjectOpenHashSet<>()); // DivineMC - Regionized Chunk Ticking + volatile boolean isUpdatingNavigations; + protected final Raids raids; + private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>(); +@@ -666,19 +666,37 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + boolean flag = server.forceSynchronousWrites(); + DataFixer fixerUpper = server.getFixerUpper(); + // Paper - rewrite chunk system +- this.chunkSource = new ServerChunkCache( +- this, +- levelStorageAccess, +- fixerUpper, +- server.getStructureManager(), +- dispatcher, +- chunkGenerator, +- this.spigotConfig.viewDistance, // Spigot +- this.spigotConfig.simulationDistance, // Spigot +- flag, +- null, // Paper - rewrite chunk system +- () -> server.overworld().getDataStorage() +- ); ++ // DivineMC start - Regionized Chunk Ticking ++ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { ++ this.chunkSource = new org.bxteam.divinemc.async.rct.RegionizedChunkTicking( ++ this, ++ levelStorageAccess, ++ fixerUpper, ++ server.getStructureManager(), ++ dispatcher, ++ chunkGenerator, ++ this.spigotConfig.viewDistance, // Spigot ++ this.spigotConfig.simulationDistance, // Spigot ++ flag, ++ null, // Paper - rewrite chunk system ++ () -> server.overworld().getDataStorage() ++ ); ++ } else { ++ this.chunkSource = new ServerChunkCache( ++ this, ++ levelStorageAccess, ++ fixerUpper, ++ server.getStructureManager(), ++ dispatcher, ++ chunkGenerator, ++ this.spigotConfig.viewDistance, // Spigot ++ this.spigotConfig.simulationDistance, // Spigot ++ flag, ++ null, // Paper - rewrite chunk system ++ () -> server.overworld().getDataStorage() ++ ); ++ } ++ // DivineMC end - Regionized Chunk Ticking + this.chunkSource.getGeneratorState().ensureStructuresGenerated(); + this.portalForcer = new PortalForcer(this); + this.updateSkyBrightness(); +@@ -846,6 +864,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.dragonFight.tick(); + } + ++ // DivineMC start - Regionized Chunk Ticking ++ if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableRegionizedChunkTicking) { ++ this.tickBlockEntities(); ++ return; ++ } ++ // DivineMC end - Regionized Chunk Ticking ++ + io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR + this.entityTickList + .forEach( +@@ -1874,22 +1899,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) { + List 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 7fe5cb2ea1c81b12baf302999a2794f20018707c..738cbde3595165e0f05c0a6fde21499e98dc850b 100644 +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -113,7 +113,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + .build(); + public final org.bxteam.divinemc.util.BlockEntityTickersList blockEntityTickers = new org.bxteam.divinemc.util.BlockEntityTickersList(); // DivineMC - optimize block entity removals - Fix MC-117075 + protected final CollectingNeighborUpdater neighborUpdater; +- private final List pendingBlockEntityTickers = Lists.newArrayList(); ++ private final List pendingBlockEntityTickers = java.util.Collections.synchronizedList(Lists.newArrayList()); // DivineMC - Regionized Chunk Ticking + private boolean tickingBlockEntities; + public final Thread thread; + private final boolean isDebug; +@@ -145,7 +145,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; +- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper ++ public Map capturedBlockStates = java.util.Collections.synchronizedMap(new java.util.LinkedHashMap<>()); // Paper // DivineMC - Regionized Chunk Ticking + public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates + @Nullable + public List captureDrops; +@@ -1459,10 +1459,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + + public void tickBlockEntities() { + this.tickingBlockEntities = true; +- if (!this.pendingBlockEntityTickers.isEmpty()) { +- this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); +- this.pendingBlockEntityTickers.clear(); ++ // DivineMC start - Regionized Chunk Ticking - synchronization fix ++ synchronized (pendingBlockEntityTickers) { ++ if (!this.pendingBlockEntityTickers.isEmpty()) { ++ this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); ++ this.pendingBlockEntityTickers.clear(); ++ } + } ++ // DivineMC end - Regionized Chunk Ticking - synchronization fix + + // Spigot start + boolean runsNormally = this.tickRateManager().runsNormally(); +diff --git a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +index 5d17213a692016d2f005c7820bf2cf1f42ce411f..ccb2e0c28aeaebbeef15fbb650fa3c2e5c241ceb 100644 +--- a/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +@@ -53,7 +53,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++; +@@ -72,7 +72,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--) { diff --git a/divinemc-server/minecraft-patches/features/0051-C2ME-Limit-NBT-cache.patch b/divinemc-server/minecraft-patches/features/0052-C2ME-Limit-NBT-cache.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0051-C2ME-Limit-NBT-cache.patch rename to divinemc-server/minecraft-patches/features/0052-C2ME-Limit-NBT-cache.patch diff --git a/divinemc-server/minecraft-patches/features/0052-C2ME-Optimize-Aquifer-and-Beardifier.patch b/divinemc-server/minecraft-patches/features/0053-C2ME-Optimize-Aquifer-and-Beardifier.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0052-C2ME-Optimize-Aquifer-and-Beardifier.patch rename to divinemc-server/minecraft-patches/features/0053-C2ME-Optimize-Aquifer-and-Beardifier.patch diff --git a/divinemc-server/minecraft-patches/features/0053-Copper-Bulb-1gt-delay.patch b/divinemc-server/minecraft-patches/features/0054-Copper-Bulb-1gt-delay.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0053-Copper-Bulb-1gt-delay.patch rename to divinemc-server/minecraft-patches/features/0054-Copper-Bulb-1gt-delay.patch diff --git a/divinemc-server/minecraft-patches/features/0054-Crafter-1gt-delay.patch b/divinemc-server/minecraft-patches/features/0055-Crafter-1gt-delay.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0054-Crafter-1gt-delay.patch rename to divinemc-server/minecraft-patches/features/0055-Crafter-1gt-delay.patch diff --git a/divinemc-server/minecraft-patches/features/0055-Raytrace-Entity-Tracker.patch b/divinemc-server/minecraft-patches/features/0056-Raytrace-Entity-Tracker.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0055-Raytrace-Entity-Tracker.patch rename to divinemc-server/minecraft-patches/features/0056-Raytrace-Entity-Tracker.patch diff --git a/divinemc-server/minecraft-patches/features/0056-Leaves-Protocol-Core.patch b/divinemc-server/minecraft-patches/features/0057-Leaves-Protocol-Core.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0056-Leaves-Protocol-Core.patch rename to divinemc-server/minecraft-patches/features/0057-Leaves-Protocol-Core.patch diff --git a/divinemc-server/minecraft-patches/features/0057-Paper-PR-Optimise-non-flush-packet-sending.patch b/divinemc-server/minecraft-patches/features/0058-Paper-PR-Optimise-non-flush-packet-sending.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0057-Paper-PR-Optimise-non-flush-packet-sending.patch rename to divinemc-server/minecraft-patches/features/0058-Paper-PR-Optimise-non-flush-packet-sending.patch diff --git a/divinemc-server/minecraft-patches/features/0058-Linear-region-file-format.patch b/divinemc-server/minecraft-patches/features/0059-Linear-region-file-format.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0058-Linear-region-file-format.patch rename to divinemc-server/minecraft-patches/features/0059-Linear-region-file-format.patch diff --git a/divinemc-server/minecraft-patches/features/0059-Cleanup-dead-code-from-Paper.patch b/divinemc-server/minecraft-patches/features/0060-Cleanup-dead-code-from-Paper.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0059-Cleanup-dead-code-from-Paper.patch rename to divinemc-server/minecraft-patches/features/0060-Cleanup-dead-code-from-Paper.patch diff --git a/divinemc-server/minecraft-patches/features/0060-C2ME-The-End-Biome-Cache.patch b/divinemc-server/minecraft-patches/features/0061-C2ME-The-End-Biome-Cache.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0060-C2ME-The-End-Biome-Cache.patch rename to divinemc-server/minecraft-patches/features/0061-C2ME-The-End-Biome-Cache.patch diff --git a/divinemc-server/minecraft-patches/features/0061-Euclidean-distance-squared-option.patch b/divinemc-server/minecraft-patches/features/0062-Euclidean-distance-squared-option.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0061-Euclidean-distance-squared-option.patch rename to divinemc-server/minecraft-patches/features/0062-Euclidean-distance-squared-option.patch diff --git a/divinemc-server/minecraft-patches/features/0062-Do-not-send-spectator-change-packet.patch b/divinemc-server/minecraft-patches/features/0063-Do-not-send-spectator-change-packet.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0062-Do-not-send-spectator-change-packet.patch rename to divinemc-server/minecraft-patches/features/0063-Do-not-send-spectator-change-packet.patch diff --git a/divinemc-server/minecraft-patches/features/0063-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch b/divinemc-server/minecraft-patches/features/0064-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0063-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch rename to divinemc-server/minecraft-patches/features/0064-Paper-PR-Fire-ServerListPingEvent-for-secondary-motd.patch diff --git a/divinemc-server/minecraft-patches/features/0064-Configurable-player-spawn-tracking-range.patch b/divinemc-server/minecraft-patches/features/0065-Configurable-player-spawn-tracking-range.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0064-Configurable-player-spawn-tracking-range.patch rename to divinemc-server/minecraft-patches/features/0065-Configurable-player-spawn-tracking-range.patch diff --git a/divinemc-server/minecraft-patches/features/0065-Optimize-collections.patch b/divinemc-server/minecraft-patches/features/0066-Optimize-collections.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0065-Optimize-collections.patch rename to divinemc-server/minecraft-patches/features/0066-Optimize-collections.patch diff --git a/divinemc-server/minecraft-patches/features/0066-Optimize-level-ticking.patch b/divinemc-server/minecraft-patches/features/0067-Optimize-level-ticking.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0066-Optimize-level-ticking.patch rename to divinemc-server/minecraft-patches/features/0067-Optimize-level-ticking.patch diff --git a/divinemc-server/minecraft-patches/features/0067-Optimize-Moonrise.patch b/divinemc-server/minecraft-patches/features/0068-Optimize-Moonrise.patch similarity index 99% rename from divinemc-server/minecraft-patches/features/0067-Optimize-Moonrise.patch rename to divinemc-server/minecraft-patches/features/0068-Optimize-Moonrise.patch index 306870c..9ef678a 100644 --- a/divinemc-server/minecraft-patches/features/0067-Optimize-Moonrise.patch +++ b/divinemc-server/minecraft-patches/features/0068-Optimize-Moonrise.patch @@ -452,10 +452,10 @@ index d03d075d5c56b7d2beb5f0aafecbb69f5b3bbf5b..ce3b8f4161dde3e2758c5d33445da150 } diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 74f63e549f8cadc80de26fcad11923151e0c40eb..c549f0203fb278a37f1c3246a98bf3d6e3216afe 100644 +index dda53860397ee52f64209a8d08a7707cfa2f7592..8acdce5a4f5546d0fb5907cfc45731c40372e3ed 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -462,8 +462,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -461,8 +461,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon public boolean isPositionTicking(long chunkPos) { // Paper start - rewrite chunk system diff --git a/divinemc-server/minecraft-patches/features/0068-lithium-combined_heightmap_update.patch b/divinemc-server/minecraft-patches/features/0069-lithium-combined_heightmap_update.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0068-lithium-combined_heightmap_update.patch rename to divinemc-server/minecraft-patches/features/0069-lithium-combined_heightmap_update.patch diff --git a/divinemc-server/minecraft-patches/features/0069-Entity-Status-Lock.patch b/divinemc-server/minecraft-patches/features/0070-Entity-Status-Lock.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0069-Entity-Status-Lock.patch rename to divinemc-server/minecraft-patches/features/0070-Entity-Status-Lock.patch diff --git a/divinemc-server/minecraft-patches/features/0070-lithium-sleeping_block_entity.patch b/divinemc-server/minecraft-patches/features/0071-lithium-sleeping_block_entity.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0070-lithium-sleeping_block_entity.patch rename to divinemc-server/minecraft-patches/features/0071-lithium-sleeping_block_entity.patch diff --git a/divinemc-server/minecraft-patches/features/0071-lithium-equipment_tracking.patch b/divinemc-server/minecraft-patches/features/0072-lithium-equipment_tracking.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0071-lithium-equipment_tracking.patch rename to divinemc-server/minecraft-patches/features/0072-lithium-equipment_tracking.patch diff --git a/divinemc-server/minecraft-patches/features/0072-Configurable-Files-Locations.patch b/divinemc-server/minecraft-patches/features/0073-Configurable-Files-Locations.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0072-Configurable-Files-Locations.patch rename to divinemc-server/minecraft-patches/features/0073-Configurable-Files-Locations.patch diff --git a/divinemc-server/minecraft-patches/features/0073-Pufferfish-Cache-climbing-check-for-activation.patch b/divinemc-server/minecraft-patches/features/0074-Pufferfish-Cache-climbing-check-for-activation.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0073-Pufferfish-Cache-climbing-check-for-activation.patch rename to divinemc-server/minecraft-patches/features/0074-Pufferfish-Cache-climbing-check-for-activation.patch diff --git a/divinemc-server/minecraft-patches/features/0074-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch b/divinemc-server/minecraft-patches/features/0075-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0074-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch rename to divinemc-server/minecraft-patches/features/0075-Pufferfish-Make-EntityCollisionContext-a-live-repres.patch diff --git a/divinemc-server/minecraft-patches/features/0075-Pufferfish-Better-checking-for-useless-move-packets.patch b/divinemc-server/minecraft-patches/features/0076-Pufferfish-Better-checking-for-useless-move-packets.patch similarity index 100% rename from divinemc-server/minecraft-patches/features/0075-Pufferfish-Better-checking-for-useless-move-packets.patch rename to divinemc-server/minecraft-patches/features/0076-Pufferfish-Better-checking-for-useless-move-packets.patch diff --git a/divinemc-server/paper-patches/features/0001-Rebrand.patch b/divinemc-server/paper-patches/features/0001-Rebrand.patch index 1d0b375..6480785 100644 --- a/divinemc-server/paper-patches/features/0001-Rebrand.patch +++ b/divinemc-server/paper-patches/features/0001-Rebrand.patch @@ -279,311 +279,326 @@ diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png index 518591dd83289e041a16e2c2e7d7e7640d4b2e1b..f54753531b3bf2e8b5377f342465e727c7da98f2 100644 GIT binary patch literal 6677 -zcmZ`ecT^MIvk65y(vr|S0wD$n1T=z3m0m+wF=$9cr3j%}P!W;dMd>0)Cy6mZP(Xpu -z`KXEn5Jf2hLO#R>ih{iOJMX-A-XCxG+?_jjX7=vRopyIq-Cd813CjzEKp-&(dmB#> -z2#omK1bMk5u9dOJxq$DSrHds9#LO1i@#p8_sw8_)7Z51s00J|A35u(#^8|4ULRXr{u5ar-vE3hmqE3r=>bw!l> -zCLnNFgew+2R&lAAi)cmJ0#RrDqXICbhyX4Cp$t%{gN6nNQN~z96O4fg24$*eV1O|& -z`24~m`2Pr82s;ya_R9Y+a5FP`iYwq7063g=aRI@(eL)aESPJx4yI}4K0?UK`s+8LU -zIf51br|${Y`EMQ`5Qs-kkkt%z@DqvQS0OciO<6(B~X-Ttj8^Ly;I -zo6TV6_jdf1w>dz}4f>(bF>w9Nl+(tmyuNjboV5a{jFW#sdhZ3z{C6FC!V#*o?@AZ* -z6@#2M7W4S(D=_e$&8q=XmdM!qgOR%?ntYTjPFBys6aK5aZOW9A-@mVhM4$Tn#+hCB -zNpgxYSKw4B-@=Ml8HJRuwG70o3_~8YcHFp3NRQPixJk)8jWlBG`$)0fR?<9ouc(Iq -z@M>AWUQmUPC;T+To4^Nb6>2S#hFq7L&p%!1Cs%tkSst0NNYZm;6BFuVg$q)J!)F7( -z%(e_;?{knc?~C+ODT}S?y_c3y-kj+)Wgt5{`{U-T!|fUc+rlYhRs);U0u{fq@D7>$ -z_>Lp=enScNrA5b3pV^mFIh4g1^)G(S4aMb`J2kRvHwN--6UVxbA8uFjF<}pE*7ZMK -zD7IlonkOy3AIJvqJ+^v3B{iHk+09aQ#>kl{ -zmaISJQBQP8%5~(PD4NTU;H% -zN4-1eLAj|t8F9I*tOJKM3*6eu_ik{zyQXVr`+F=q1YAwrdHH=#%BbwO{yyyY;)#O9 -zGoK`Ujx6-fNTj483E1!FGtYVz6zXJkTq}>qH=7wK@z<-uMz+lx_|+jFzKR&rwU*h7 -z-SX~-k+=i6A(lrB*0r`9T8GUNIhfO&-z;_$ZArSIsvPp?xN$s|$dHe^`OM^F>B%4e -z+B+^26JapEmg)E{;0#))&Eg{uHb-Q`84A;T-g<0_D1txOzm@fAkH7Bi)a>I9KNL*w -z8u{ixFO8tyq?{r4KmQm -zSNiE?)c%L{xJxhP4&5oKhr-|T5c1%mU!3b24|v+PPTx7XiKE<3_og)W8hwd4bQ{h> -zw@BZ$Vn;F^AsxsUQYH4)WS37yHJ(jv^McSfJ!KYWI{j#p^1Z|(l4aXFHm%b)_D;p6 -zeK-F2{zQ2YFT{AfE%kmcleZA9 -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 -zKQC*8IZKJ85gXf`D@XmrZ}z0B4$-% -z#5u_aJlT~Rz#nDlIJ6PugYP20>(80*@KTjt2Lvz5mZ0M7$)CcUk@p_s$^h?o_rF$>!zEoV+I-e)}5CY2o9PEjay* -zV>Cj8ZChL}gx7qpb>?}aNx}GS69W2l#$e=$@mq@2rNQ3ZaqlTtH2F0b9YVEg_&cmp -z9vx$cf7u~q1PkZir56Xw60;6fM=X)hnQ`bvgB}QZiFos!aZPc!EHRvJhPYeZiG3_? -zjZbnKVSm#-9*)S}?Zz7Ix5mdiDb3_8pG#x{I61G8qoRfu1(?S9zqVOT5UPa0RFVoy -zxGZG6EN57Ym|95?5w#v3susU+2$|LdW!O*>lhl?!cqW?wb$~FN*e&rbyxv*?dCe5X -zA3X1$($YNfAX74Uu7Tv&Y0zVaUwg5SyFa7>J}6Pc<8{{Dz36a2cWZ@ziU|3oYtGnA -znJD06B5HU9wr-RKbRVXY{N@dMhVhN*V%+a3VjRb0wX;hVazYu=%el;UduXEp%w^7< -zb|+!8yUq+Ya!HO6tIB5eqD~poR2H$D+@pe77pwERgEIA -z0!|y>AQ6FFu;Cr?4;OGC36S8`-RHRs!ojv|9~nbh^^c7~^@OJH?SB5}xeQZzNnGTp -zU${G$vNFg^JlLjxT2*m!{P!2zieBFsmDoj7By5jYgbdVWx_kcpnE-OIb+w^e5#s*~ -DA-Nv< +zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rT@h2EWC1?hFhJEa{HEjtmSN`?>!lvNA9* +zC?tCX`7$t6sWC7#v@kIIVqjosc)`F>YQVtoDuIE)Y6b&?c)^@qfi?^b46y+|A+8Jz +z4AzE*1{#{~F76Sb5mpvfPWDb-4o==4-paCa1{xY-Lc;2bN^+7?DspmG=2rST`W|i` +z=BDO)>Kgib`Z`)VdK#K$#%3zYDt1+tPBi3T(HkZ(U6;;l9^VC +zTSH@S`*j8ehN#pC&op0O1}z2#1`Y;RMj-}J=rS@eGB7YoF@S=Uk%581i%}ZR4r0`R +zs$pVaU=oJ1L8=(Qzyst71_lN&Eg$sVgn>cA)YHW=q~g}wyDyzqTL~~ccwP48O4Nnm +zH%YbsukT6qoMAe%CE%4&{gx>~pEwm~viy0!|Nf6&d13SC5moa0Jnryp{8CrbxPx)y +zmwhpncP2zs)vvS2JI}cC)^+dqm!}?kD=^{Jbnl*M5Y>G&S7qA0{n}hb3U}|#eLPJj +z%lrM~sVplOS!o^lTAf=}Pc+G&5nZ@ze|<$lcb&%c##O!Xdd64v!-cN;Kko|q +zTd7d^J$UD%kX!|=OD#VPW6ZQpxJoa#Z#(VxbVtVa=f?|{25xnF1d*Q{{9zVFI(}8GFZ@uogp}^Jh$6k5icQ0O_u$t^4QDNUcK +zb;MQshoG|0*Q+~(R+#ABDmfsLxN7~8(%EjRnHLkx3|B9=uiwWcKG!+4rE5;<#?2pA +z{=c)e_~OmVqbnHv*VNTZ*;k*9DY=&(xT;b8T2aNJ`TN84Y%;%nn-;psf66OOH`m|i +z`*RqVCjGhi<$;j#{NMU)Azx-)nckZ6P9WU+(a~E19bI|}Azw0j(}JhZ(CFJ=v!E$v +zhmCq-Ujvp;P&u_}o^`NVCqPW9Q<$A_f?EcL?F!cHFutP1g4epqZpNFTTEgdNj% +z@HUz{Cg&>1<@|FuX$nc&AXU=1+w8^M=~~tMDe5RqyFPu~yevtsJGM{;#Tb +z{Je8gU((FiOtr@ZLbr2gvYvhHwNBnLe98HUCT+K`E_#_xQNr6RjQH2C3@g7VX)$^B +zN-?cFObJu9@;>^k*rFEXy6eW|=&xa`CU%Fe+HutQW0A!~tplbzg{L@OE#BxQx?k^t +z&}@&T1-|c$mj!Lz`;bHI_L2GaDFpFiBZ_L9tS0^ugd7!N6$um~HJ&YcyPoe}@?XQ377r07#oBR`D9&d@29XU-~HFm1s +zWcc0Hek1(P(vLF7qt@oVl=La*4BRTHrESeSwQ;V9-p>!*K^Kh`{J!QK`V{k6{pCA_ +zRRZFxA22^o2-EwU!yDwN$30ba_2WbHm$6$dy0jzWvZ7H=#zU^~JV&kLsf#xyuMNxL +z-lDQa`P9yc&ma7ClA>xBG_4a@w&>(dfl#h%RdbK2_FdXAtwbn%PS?7lX3xK!@%#E| +zQtQ-1OZl=k`nAtI?Z$dtWTn9LMlI>nr$l9#Q~nwYPoH~g?b@K9wkCnT2R0Qf<)7)c +z^U{hVzL%t~dYN*b4!GJr`^%a~dDlIxH@#3>l6^3C!mGBtNupVsJfuknmo^QbKQ +z#%rBlZ6&$~Vs5osxlC={8dtm~N3V_HI!DmYO&86#PCfpfduwLNDxWoS9LcGLh8(-x +zCaltqUQ_fqX5+K@Zc}@&3I(o_xITG8-vQQY0i~FVmv=Xaz75|nZIhQNV|LHgQ-@5i +zurl_rtCr}!ovR@Fu1z(-_s}Y>zNLkYt9zP03UElOmYiW->9$Tqt3C93WQ6VYEYZhG +zZ^aoOD+=M8)^t^Dfu-w;qK#I1U8cRS +z=l7dvZO~f%AXV$Y(RI!%-g>V1wDDYwjQ0H3@?9pY8oNzpOI9^@Z!Pd}o*UqMFlsMX +zgqfb1&hLIVsjJNf6Hc%G8j;oiHH+h_$(rlojN0d}zLh*%$hPxQ$d>nqR^BoQWL&d- +z`=kij>#wu9rr)=Ysb<-c6EeYj8B@%|zOxCT`==hWD&D*A*3JuZb`#I+JdwJ*D8}mQ +z0nyjYe0QH(Ziw5yK1|QHadDyHOogd8Hl+Gqh$yc#E}1SF7R;0#-Lcx%u_?yqv0Imc +zsO>&;o3?jG2eW25MX2tGxw^W@uvc35P{;)D1-E`|?hTlFc-ARa{Z~rjmv?Zw&Nx-r +z8IsQwc3I@ut+1alTV|fxkvB>CTI@I9fNQa75x&OEVWo!aelS%n-5MOYX4y>6*G4fP +zS-0>`cWT`@E6r`q&z+CBGu|uoawVCbJrnV{=&1OGx^%6p9al}n51e`?WF+)osJZT+ +z{@J&#D`l?z{w)(>-8c2=(Gk6H{W7p{CVdY7-~0+Ccmr<2jG3$+G?8$2JwO +zeR+Z{d)cLbMV70UJ&ZWMxZ$eF=cLG;*It`0niTc5IIwWd5IVKtYLP78%9y$~zb)Oq +z%62>p17)R^ucZaEtbVQ(Aur$VtR+6&4PE6kE6DE=^@o;{VX+dp`%Z_u}r(zEEayYL0 +zR;m_yc4G{)ZP(MZKA$76cIZSHT~~a$j`zD&cUR)ouTM9gi!sybeEnzM&vm>%teU$L +zu6{L&u+|oP{_39T-K~zwGr1D4Zf&?4BPn)v8Q=S2orN>IoMt?fU&s_us+(YXRwv?} +z){NHHoqwd9_^V|XJ&G{Y>OZ4-+OJPM%bLJ14+*lx}O>? +zF;3k2G%bQ%`PzxrTWg*8tJel5>Trj)AAMD3vP0_dtVyL0BHEh;Uq5y}&=j+evFuPt +z-KIC*T302zw@Oahuxwd|McDD98?^ea7H^ajJZ{Cf?rd9fhzU9dlX@^ +z`to}H1WUb+r#p82RgWlJe#B+-HD|!EZH#)Y^RSb>ARA7W#cU-jgXlUcm2CUlMXl?vnsy1;nsAK +z*NcTVSm`mY)^BhUJv!;0L|xJvqs7)z)2??VHk#Uqy-eCIYB^22!AbPsDrd%xUc9X@ +zBa(NUG#%aHF~2aUK~N|Esz%7U!%KSv!(yd3p6Zp}bdLMgH;IiL;xCQ0BL2y=MED-w +zcqhOm>W7TqLC3HQ+9Df{{o7Jtd*rNs-_xBcI`P|`*VG=~ct;>yF6{D|meyj^eNTec +zxgB7NS-`t2;inn%5hm784<{X|jJT`D5!R{czQukov+DFBQ@1sJ-HCfSB3`WbU-4-} +zTd%^JT_^tNn1(*SJ@?A7j?!mF2@```1D+=QJj<}=UGL3}QR|#_Ox9?1eckpvqT<;h +zg#*=d+IbO#e +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 literal 9260 -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 -z<wCdy-3tTl}j4kzaCmrni9Diizn#a{@0 -zu;<>ZBofe$`#ML)Z*Aj8mbPS3-(VgSdF3LA8LJgBPj{3IaB~uLBuylKO*>ev*i|tuS(Wff3`Ogj^{GsE -zb-&NcY_)d|4#vv+AW}skSWrN{p$KOp?oug)BPoM*O}*h=wrr-PGYCt{qwP-&I!~hn -z&+*{EI5^09slk8i%kFcTjCcO6Oc}M9iiS}cuLLw0fyMPfjZ_M`;HWDHP^ke=f*5^! -z(0!2p!N9nZ8J+AP5sfunmbw64l@2)3@53_`Q@g&4FYKeDLbz2F-Pl@Er#INAtM()n -z<;MFT;osC}L2=Y4P1?cm)V{7nauSgh -zx4)k@#lLT}(uM?{Z&NvzT8pnJk@-MDvv4wOKsY+l9S8OdOw}cex#$t*B6ppAEloQy -z8u`9L`Ky$*$*G}A=)h6BjVn=_YuPie5epXe0vLKZP=Pxps%a&uGrdg4y#R{YobnDn -zWlMl5J;9|5ev`f`BO3Uh(yuK%@i^`+fAimq+_>*)z(;wrFdXn2nVJw1y_>PcV%p-) -zt#ZCU`}~DIE5y1BiI$qSd5XIebq(uRB-FnL#^x=bDHO-ls3({4R}-PgePOPH8ggGN -z^EAdT|N11qATWCZQ}ZY#=hum&;_xeyp*|O{VN?%jM$?&+DK=8LzLP4?U!YQ_JT0`M -z`m!W@TCB5mlr9&jJ{^cX4Ye=uf(7g!BDG1LQfZM#P5u-^$L1K~rOMk7oWI24W>ZJVoZ8!*NX>jC%2pgw@7$v*amGL8JnA`*TjN)y=JPix$ -zHom^xjfr~ZFvhO?xbJHg&jfEZgboIqN@pk*%G-#&cX5DM>_>dMo{P<(#6bOBlgEyG -zzi7pMrVsz<*TT+n%Xo*+rUVN -ztJqe<9EEg`YU)i$PQ+gn%oA5sG>b*6QUjZVf+Ju4QKWr32^B^>#t1pQ*dNT#SxuC8 -zGNJ9mH6R-92O+m#!DECXMrB|3+|cZ$?^qoag;w8-vr)Z5hx@2MVoazOwqdLo2-lu( -ziwF(a3SNH{+U_=d6KFp}-N^eInrfTZ{p%Yc;K{NXO^Sl0qy(%)%sUXL -zA6Ic}&$4}O+ulD-?|#%otX@aO$zD_RW;|WXeL`u5;iz`2Ja937zabkT*wwyB&2HIU -z%>tpNcvDWCsG=IjRr(V|Z7N`9^tphbhiC}fIrVcS>=>)uMStm;g&z-HK{fFz2ud&X -zKo;y87PhB3IZGZ&D%bJ2dZ<-Z7I$fCrPWl6O0ir})>f~+rM8k@!Q(EpWCD9f!k>me -zRhs@Q3_eZ!{s3QHUMaN0uShhn$y!N+)a -z6F#K#O21}#Wz2NGar1LUq3S|3=0~&VTjxVeqcysO1QIGwgglMcjXc3^9R9i556MW! -zA%G1+Y)mPX16RcVB#B?R~Xl -zIeR6G9EBEoU+Sk|=Q=4gQdT~j9ecG~G45m|E+IkhfuBxT`M%^wZkNkXpL0AjS!$%u -zg-={lr6QW@$p<#-f}T{y|0rAEpY~$9`Ffd=BP+`1#;?ge=@mLGkdmI~u?Dai2i+}> -zr-d}7M&xTHsK7@<3$tPd^Yg3fLzxDa!oOJ_N!hGt&$}5!9&TOIuzhIP>)^&CM1CIF -zY>A-293)fzq2lbB(1wKk=>#3=G1eTT&8(iBSJab=V@AGnDSwOhxKg{m8sa~TR||^x -zH?*-f-l|Zq;GkYEt~~O`56i(Z6gi`*^TxMZuc-f=NMlvry~%u2a>kz*@R^tJ@{7%-A@wfa)Z -z0~dL|Z*tTjEX7ED(M%2gZ|Zi_L4TWr%=BR=y4%;?-COo)8t(xaW)#f?Uhc9^d-1?K -z=UDW-cu8J#%~t1$>T7o{K5NXC7Z^ -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 -zWZQ?eQkgCCqwANoAm&K4|fw*k7ipV -zB1v2pR!seE-oV-2@pAb2ne;%k;&0+LB7z16@)VH1MO9)MHU9kSp)dCNVB91j?4mmO -zv3NP2%#IeX=+W7Ni#8IjoTpc(!3T*dt7!EX8VlAzQq6uvFcs%W{$71OuAvW8Wpseg+*PVYLv?WMN=C|H@$;E_S5fVp$L;GyupU7jZ$kfvC58X?uLqEZijH!v -HqBZh=dic2S +zcmeAS@N?(olHy`uVBq!ia0y~yU^oH79Lx+1471we)-W(I{SEL5ab;j&*zEAXF5~}E +zga0u-|5FKJPi^?W!SR1V#sAsC|8uJUhfe&z&gK7d&;R>O|DV(NKOy%25rhB6YyQs+`9DA4 +z|3%gRmz4isR{DQe>fa*2|M`{wv+6)wkRP|JySE-tqjO5%zzj`~TS?|Lqq2Kd$@#pwa(% +zK_K^^)%c&<_`fa(q-#?2|HS5hrA7aNBJ|DTBbKWy~hY5xDD=KocB|K|q%k8l5Pz4U*0FUT=Ftw17C-5?)LivHi7_e`Bnd?M*c4@1G)K< +z%Kw6LP<~1toyYy8jhL|I->k9$D%QN-E1e|Cbj3KcW3UvE_eqGbnBJ#s1%828y_a +zejqE>JN>UJ_bNd +z`hTk}DC9%?{@s=Q7ux~y;~~TU&xHS5FZ;jC0u+Nf8~@j5|Np@C|AF{F*SY_Frv2Y! +z|GzT{l;pm${STV>za{PeW6}R_c>kL(|9?~FpZ}EqvqJydEdHNf_wS|P|MG@^Zp|@8 +z3=9k#N`m}?894b^+5QP>J1X;wRB*Y=c539fqD_#g}^n4fMaf +zTwj +z#M$P{hj&}bKU_GuzAohLgIm|8M*Dw#{P5<&1x@jv-(0#bA-bp +z_CUjo4HG0)n3W!|@7LHaqA~ZtsTl{DIC{Ey4vFniS-`F4qL6m}^Bg6vFK=&)iT;a! +zHaq9s{O5npSI+xi{NUa$o5knU)3tY)>Oa46XwIA`-gl&?o2=SXoRqX^_wEk{+ow&9 +zy~ioTz_d&A@wHWa;$=$i4||{FT}ioetE9_h=VXf{(S#p|JTG)_3chnII7hQk#OigJ +zy0Amso*nN_uGN)2C+X5Rr}eVeqcApw;Na=1cWzC5{?qZn42|=3pB46T$}Hd!-0t?o +zzC&j2ze}pGr*O(FUR;=cSnH;%!^OL`at700h1_}Z;>F+JJHOq@y8h59rtf1?ZTQZV +z^gFcy*HbmO&w4t?%$h^1`|0oUzOuXTUrBYBJq}x|vT^B=i8&AQZ{K5gIChM$rC@ci +zc^AjxfV3GF7KJ%EDK4)cA6aWx`HW{#*CtEFpdxn`O64 +zsd!7XFSP8LuAx)qw>Ip0d*S=|f0r+3^rv)o*7GvH`t|GAsjBjKf3NCanIKi!AkAle?Qm}5i@1Yg7_yr$&IOQSxYBq +zYlp6yewEMchbn)+<&Sq{^t=AU +zmQ&QH#T)&)6B-t_N=y55MmVdPusctKO;yR!S=GBg=}0<=#y&~vTw)yA);%TGZ)3)? +z<$+VDZ4&xobh>k$>-)C0Hv9H_5_}hx4PZmb!XcniA^R;BqHuGdHrQ%newK` +zTg={-@xAZNgGPcOl~?=hCe50td?)jwqreVnhk3RiA|h97Y`b&lsl*MXST#A<`TkRO +zdQNz)){vm3^-%wgqnA;8FLPpr{$uvpC(_T)v#q!wwWUeMoa@%a#V*_a%sajCnc%;xZUtNjM>h7&uw}0y#O>#YSxa`W>h<^+D&K0Vu +zFV1+)dOUGowf*%YwKh#UzTg|v!nbYFH?L@D +z9G+?S$l$)L=a!lNbxS2gkv2xtX*g&zIz;Y`nB&UO8{^*sui^N!6e +zm}zn%art_k@*J1jmx>hZ4+I%657fRJImPvFW$}W-Z(F-(%zXL!_2;`;dn^Nv9!uPy +z++A}nE$CY(LsI5S#!>*k?8N=zM7id^DZ@1d*)evhwpUZ>o(7= +zsctdi=j`=PpU`6OaF$JQPteihynlYC0=GLuW;VC40OvaQ4AWcNXULSty3Ou)Ij%iH +zTizkY`GicR)|5+6e%0JIR9Lx^(^gq5tY5&r({knP$@~*CwstBC#jxE@_|wk2gy+VM +zwwncN-Z@img#-r|m!H==x8M?o@>v<4D!B)XuVzIr;&i;;nDAdv&)m3D{QZpz@he|i +z4`%lkzF5V*S&X&z-QtR?O$zO&826pM(syCEudi<%+xn(xj-Ux?@BV+7;_vO=W_9^Wi%c8;gYJ+p&7?^C +zh@@G;Z%#hfwR>~o)FMZ}rE5FZIp=3_EL?5m8vo(I$kbb +zw{G#`WNCYj(!h?O9u;QR_Fl`?d_6sk?hJp~4ti!iIiO+~vGUNrX4QAUliL);YKx9` +zgvHb>(os{F*X?m%eng+U6gD@ZTC%|mb_T>u5w+e0<*$_z&myfNz2zCntzXx=a)9i%w(S1 +z{Tb1$wijmv@3$=9w)@r{hOWf0pP4TN+4hLD%zV7sET;d$+B2Fh54SIToXO75q0{CP +z=I}F*FIV&Yp-7o0Q{tycn7H4O_!juteI1)+LAY*4y~WQzchVkNedl1lx0&sCc;O-2 +zCo4REaGaeO5Z$f7dF?mDkyde*>QzieR+~>9RWdtac_zQ_h~bkD7oRFmliKRG_epM> +zi=4CD|IWy#Dy(~+$5a@8YZY?aWh%Ebf$vJ&*9ViA`_GqRc{peL22Ky1T+RPMRr{+i +zNA9=m>uYr5+Y#tB-;g~>`|0VW*6i&k0T +z4~wJ!_6P`A)n@()tZH5w_NKOakCVUcrK_!{1^wlJu8}_@{4z6gJ&!Hp+`Y#x_N>}3 +zUv%-VxXQ0v{7*RkI`+uF+`47$iW7@Of6hLxobV-lx{d7*$t#hn?QE7$Z=ODz&6i+r +zF{!(5!W^$F0rnZ^C%>Ch+tO9CsDJWWi4XI(L@kr^v?zLiZ|}BQELOLLoH`F@+b(DR +z`8(fEpy21D_F99|a{KR$py>+&}TNm&qR4jJPP;<4L-?4~!D(jxff%&tV4Q{LxN_AMsvC@Cvl?N$* +z)j$1wr@+0Xi@j;fw`Cpi=hyGgZn>Iqdv|wV%zCvaH$GRL-0f+>VO@K3hVksPOXBu4 +zgly5Nt8>>bV`96Z?CfQmxJA`tvigHxOJ<7PdiIu1FG6jL)=aecwy|IB +zk%#()R?(lY_2VYIJSv-P`Lm`@jaA`8(EknZPVDVhNa4#`!oa+3hQdW3uDgOS4+UL} +z>u{|uVPb!<)z?aYF?Tf=^Sz6wxz5>5{dtGfdwpilDSnG3@I`37yK^w$N1~yG_MzC`{}soHM_8HO{w6K +zJC4iO-}rcfXP0vAY`s*63B7uA%@AW`bimY +z16x0pZaKz(yu)t&*)YqSx$>LH+9YRvtD?Qm1l?LnG4U> +zACL_dt=``CFzBXR{jRSsb8|0vw7%l6HT(OK{eG82?a}Z@mu3`e2`h?OZ22ivY;fai +zd+{8}BCeUt*O)9W=~~21;P+utJUaR8ZoSui>he!E*c_d?b_&;w$6sXQU$8f_92T;h +zQ2*~D|0Dj;MGF_qJ-2%C8*LS-&qChC^%<{zbao{MbalkOUU-B5mt@CE^S_^0zf@2; +z?-DV|rSGIB17F;P-I5YzaiJ$3THA+hUUl#wW9^6LKc|?PuIi-+*cq&?4OMDq$WK9iO)S +zw|KM@5=(jd@5OG|7}L`5CtL5t#dU@;6EiHzb2IfaxH~y*^3NOp64>@@UDvBgkKc&2 +zeN&coIPfy8&GFyg>GDe^8?U%y$TBgjFmHm$nKe!aS6s4K-LcKMM*8$t|KI+^Y*5m4@$EceJ` +zrNOA6tju#nh~?XcrMjx&mkxYe)q5fKYO{i1*n{$op)96B44VWUX0bH>NoQCRtkGdC +zwx?2;A?W?7OU}`vwr4nm6GW$b=!mZNW9cm29MvPaCn&o_VXKovU3{bH#YbHSidc#d +zuKUv0ldCDs{;luLgoEsodu=z!iLP1t=|irIfWCNlGS8B2VG<|aYqKqC+~y^6rmpYk +z!A@Q-!w0$FwmmmJ{!&h)y5i?c!HgvdrVpHXie(sXD)Kxjuba@B$EXm+B6!gD#IM5! +zs=PTjr&)1g!>f^YAuah9&{a; +zxYRmtuFQ$&SBt8?%6BL@`!k7F&71hp+NeU>`PmC*(>ApiWihYrsxhq;X8APxrUE0& +zBOZ7CrU`E*zmSdGk*DVR^WDwVv>-Wwgo8~JEUzU-FuiX4t8mhZJxHD9$?W?-92T{# +z_2^!zy@sQQw?rZ5jHliHRkJ-W{{B|noyHdJui&1)gjd_IO;EXXp|#LY)3p*F<=ZES +zM)Ejq;>%fPxqQwYK@a|~^Wz2g-n0F>$nV9ciFOqp*D9WTtx1_%s8IgyLz53zgrGNX +zE#VlwGsz)nO3g7`$NyM&uBswOQh9g +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 +z%E>H+(#~Iu39^6niZ{|Ww56~q +z$YpnIJIK=%X4+B1GwtS7!N$o~V*XX+zs)&u&(5JFe6`dOcY*%&_GP!Ww6&!<1%b$L7G+Fg|x$!6_mNq|G;Vt&LYl417v`Bqn +zlHvrurUiKmCJ1hic5++hoMYN7bIf_2lP(M2k=o0O%jYY4EN4==d|j~N#Wl%^0#~w& +zm!EgHkUcf`@CSWA8Mg&$rks{_)=Qw@ +z-N|oNN=inDV%+;}2WnEL$XFjfs&w?~C(DN2*S$Qn9ZlAp6aB?;O}@Cbf_cKGxooQ-BbXFYi}*YwPRnv{#lH{C2Y9Q^(57{d}*MdiAVU``_=rwJbm^93b3KHfT- +zej+w-y7xZgj{=SxYL`x!*l6jz=ka6fn}I3f=^6o(l|00qH`J%{b{?p+cD}V%F-b}J +z@sS(3!s!N1_nVsg54UcU32Jd+zO;_dGtE7AoyFn8w{AVVzcVydy>-7PAhN_v(|ON5 +zE5)2Ri&IA;JEq4~h^Gozo4LIYZL|nAUi9{3)kML)8Rav5=j^?}mlz$w_^2evO-f2c +zq4eIzyN}kmtGw;Lm&57EXgf=B({gi8&uM+w9XY~x8K3b +zu9W2{P(5+F%+;-Bh3^(AOjP*Wd9!Uo8(VRQT-;f{Gw$bdYo=Vc@A>uMo9XAK1);qY +zlr;w)32R%b-4x}&GL^pxH|6}IQ6}X*{E`8-=uS?KdeqQJH6t3#KE>voVS-D +zD0X${QX$sc4?mPVNj=kcgQvy)}(K{kW6u)1>G!J8-?Hl%jjkjEJPf +z^&dV|woN*bIibpaNww9HFy-j0W*b?U)s5K%S}$IkVDw$UaYN+}6J@3L^Iw;)o6S`y +zu%uc`rTn@;(vq~5MjDH_=870j+^qP`;rWdNJ-bwIu2MT3*VMeegKKw-h0JB+Ndb?` +z4hP0+Ppi3c>A`~c4@yqR$<<|-PfUI?=e+wBCF7~@SEt@waH!Ctt>^8=;O7rYayE2+ +zR$Zk1vnqFv7{7;}^Q179+*eYgDy5PiD4>%l- +z-4Sv1&bC`5wsUHN!is*6V{M-&9(>PqL?~se-l~p`>772;p1XS9-_U(&gH>jD%)6h4 +sPuTcv7jDytWnQr+YqnZRA=~46q4sdGkFvem3=9kmp00i_>zopr0DAbi?*IS*