diff --git a/patches/work/server/minecraft/0078-Regionized-Chunk-Ticking.patch b/divinemc-server/minecraft-patches/features/0081-Regionized-Chunk-Ticking.patch similarity index 95% rename from patches/work/server/minecraft/0078-Regionized-Chunk-Ticking.patch rename to divinemc-server/minecraft-patches/features/0081-Regionized-Chunk-Ticking.patch index 6b6b5a5..e3b20d7 100644 --- a/patches/work/server/minecraft/0078-Regionized-Chunk-Ticking.patch +++ b/divinemc-server/minecraft-patches/features/0081-Regionized-Chunk-Ticking.patch @@ -23,7 +23,7 @@ index e72eda830644851656fae3118c513d7bd701be45..4ab30d291de7db5ad7d5684662f41348 if (var2 instanceof ClosedChannelException) { LOGGER.info("Connection closed during protocol change"); diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee4019e6e1c7c 100644 +index 4fe0f6ba751666e436053536f7607fb50c8471f6..a2be5bd7167b53ad7ce25f05fac46afad669ae9f 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java @@ -57,6 +57,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -47,7 +47,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 @Nullable @VisibleForDebug private NaturalSpawner.SpawnState lastSpawnState; -@@ -153,32 +156,241 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -153,31 +156,246 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon return load ? this.syncLoad(chunkX, chunkZ, toStatus) : null; } // Paper end - rewrite chunk system @@ -130,15 +130,21 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 + + final Set firstTick = java.util.Collections.newSetFromMap(new java.util.concurrent.ConcurrentHashMap<>()); + -+ level.entityTickList.entities.parallelStream().forEach(entity -> { -+ long chunkKey = entity.chunkPosition().longKey; -+ int regionIndex = chunkToRegion.get(chunkKey); -+ if (regionIndex != -1) { -+ regions.get(regionIndex).entities().add(entity); -+ } else { -+ firstTick.add(entity); ++ final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator iterator = level.entityTickList.entities.iterator(); ++ try { ++ while (iterator.hasNext()) { ++ Entity entity = iterator.next(); ++ long chunkKey = entity.chunkPosition().longKey; ++ int regionIndex = chunkToRegion.get(chunkKey); ++ if (regionIndex != -1) { ++ regions.get(regionIndex).entities().add(entity); ++ } else { ++ firstTick.add(entity); ++ } + } -+ }); ++ } finally { ++ iterator.finishedIterating(); ++ } + + return new Output(regions.toArray(new RegionData[0]), firstTick); + } @@ -236,11 +242,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 + return regionChunksIDs; + }, REGION_EXECUTOR)); + } - -- // call mid-tick tasks for chunk system -- if ((i & 7) == 0) { -- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks(); -- continue; ++ + CompletableFuture.runAsync(() -> { + try { + CompletableFuture.allOf(ticked.toArray(new CompletableFuture[0])).join(); @@ -274,7 +276,10 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 + latch.await(); + return true; + } -+ + +- // call mid-tick tasks for chunk system +- if ((i & 7) == 0) { +- continue; + @Override + public boolean isReleasable() { + return latch.getCount() == 0; @@ -290,7 +295,6 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 + + // call mid-tick tasks for chunk system + if ((i & 7) == 0) { -+ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks(); + continue; + } } @@ -299,7 +303,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 } // Paper end - chunk tick iteration optimisations -@@ -503,14 +715,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -502,14 +720,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon long gameTime = this.level.getGameTime(); long l = gameTime - this.lastInhabitedUpdate; this.lastInhabitedUpdate = gameTime; @@ -325,7 +329,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 // DivineMC start - Async mob spawning if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableAsyncSpawning) { for (ServerPlayer player : this.level.players) { -@@ -554,14 +773,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -553,14 +778,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } private void broadcastChangedChunks() { @@ -350,7 +354,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 } private void tickChunks(long timeInhabited) { -@@ -611,23 +834,27 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -610,23 +839,27 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon filteredSpawningCategories = List.of(); } @@ -393,7 +397,7 @@ index a76f7ce474cc1d6ff918737e845666a7529bd4a3..af3875e88020d6265522f07b263ee401 this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 3c1795eb56900cd80cfec38bd1d922d566463ecb..97f3c9de6e472fc271afd3373846cce954293997 100644 +index 07138e724d46ecfd09aa75008428502fa01c05fc..d4841095157106c3c69501ac2cd09511f62cfea0 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -191,7 +191,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -405,7 +409,7 @@ index 3c1795eb56900cd80cfec38bd1d922d566463ecb..97f3c9de6e472fc271afd3373846cce9 volatile boolean isUpdatingNavigations; protected final Raids raids; private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>(); -@@ -798,6 +798,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -806,6 +806,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.dragonFight.tick(); } @@ -419,7 +423,7 @@ index 3c1795eb56900cd80cfec38bd1d922d566463ecb..97f3c9de6e472fc271afd3373846cce9 io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR this.entityTickList .forEach( -@@ -1813,22 +1820,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1828,22 +1835,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) { List list = new ObjectArrayList<>(); @@ -451,7 +455,7 @@ index 3c1795eb56900cd80cfec38bd1d922d566463ecb..97f3c9de6e472fc271afd3373846cce9 try { this.isUpdatingNavigations = true; diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index bf38e3bfcb0b96c4529d5e535893043512f52b02..82afe39d85395182acbd36a89db7b4436ecc1297 100644 +index dc82e12783989c307be2ac709a21321dac25f217..f6b548dbb8b1bd82b5ddc73e2613cdcde059ce74 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -106,7 +106,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl @@ -472,7 +476,7 @@ index bf38e3bfcb0b96c4529d5e535893043512f52b02..82afe39d85395182acbd36a89db7b443 public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates @Nullable public List captureDrops; -@@ -1501,10 +1501,14 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1503,10 +1503,14 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl protected void tickBlockEntities() { this.tickingBlockEntities = true; diff --git a/divinemc-server/minecraft-patches/features/0082-Use-fastutil-for-criterion-data.patch b/divinemc-server/minecraft-patches/features/0082-Use-fastutil-for-criterion-data.patch new file mode 100644 index 0000000..e0e5ac1 --- /dev/null +++ b/divinemc-server/minecraft-patches/features/0082-Use-fastutil-for-criterion-data.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Wed, 9 Jul 2025 03:41:32 +0300 +Subject: [PATCH] Use fastutil for criterion data + + +diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java +index 8efed0ffdc906b6c1ba054831e481f53c11f102d..1aab02441e4dfa7703963855d77bb918dee7a6fc 100644 +--- a/net/minecraft/server/PlayerAdvancements.java ++++ b/net/minecraft/server/PlayerAdvancements.java +@@ -61,7 +61,7 @@ public class PlayerAdvancements { + private AdvancementHolder lastSelectedTab; + private boolean isFirstPacket = true; + private final Codec codec; +- public final Map, Set>> criterionData = new java.util.IdentityHashMap<>(); // Paper - fix advancement data player leakage ++ public final Map, Set>> criterionData = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(); // Paper - fix advancement data player leakage // DivineMC - Use fastutil for criterion data + + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) { + this.playerList = playerList; diff --git a/divinemc-server/paper-patches/features/0020-Rewrite-ReferenceList.patch b/divinemc-server/paper-patches/features/0020-Rewrite-ReferenceList.patch new file mode 100644 index 0000000..1135f2e --- /dev/null +++ b/divinemc-server/paper-patches/features/0020-Rewrite-ReferenceList.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> +Date: Wed, 9 Jul 2025 03:37:51 +0300 +Subject: [PATCH] Rewrite ReferenceList + + +diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java +index 2e876b918672e8ef3b5197b7e6b1597247fdeaa1..94232d9ab2b1b064c032d9710734f6fbcdb52e10 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java ++++ b/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java +@@ -1,142 +1,26 @@ + package ca.spottedleaf.moonrise.common.list; + +-import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +-import java.util.Arrays; +-import java.util.Iterator; +-import java.util.NoSuchElementException; ++// DivineMC start - Rewrite ReferenceList ++import it.unimi.dsi.fastutil.objects.ReferenceArrayList; ++import it.unimi.dsi.fastutil.objects.ReferenceLists; + +-public final class ReferenceList implements Iterable { +- +- private static final Object[] EMPTY_LIST = new Object[0]; +- +- private final Reference2IntOpenHashMap referenceToIndex; +- private E[] references; +- private int count; +- +- public ReferenceList() { +- this((E[])EMPTY_LIST); +- } +- +- public ReferenceList(final E[] referenceArray) { +- this.references = referenceArray; +- this.referenceToIndex = new Reference2IntOpenHashMap<>(2, 0.8f); +- this.referenceToIndex.defaultReturnValue(Integer.MIN_VALUE); +- } +- +- private ReferenceList(final E[] references, final int count, final Reference2IntOpenHashMap referenceToIndex) { +- this.references = references; +- this.count = count; +- this.referenceToIndex = referenceToIndex; +- } +- +- public ReferenceList copy() { +- return new ReferenceList<>(this.references.clone(), this.count, this.referenceToIndex.clone()); +- } +- +- public int size() { +- return this.count; +- } +- +- public boolean contains(final E obj) { +- return this.referenceToIndex.containsKey(obj); ++public class ReferenceList extends ReferenceLists.SynchronizedList { ++ public ReferenceList(E[] elements) { ++ super(new RefListInner<>(elements)); + } + +- public boolean remove(final E obj) { +- final int index = this.referenceToIndex.removeInt(obj); +- if (index == Integer.MIN_VALUE) { +- return false; +- } +- +- // move the object at the end to this index +- final int endIndex = --this.count; +- final E end = (E)this.references[endIndex]; +- if (index != endIndex) { +- // not empty after this call +- this.referenceToIndex.put(end, index); // update index +- } +- this.references[index] = end; +- this.references[endIndex] = null; +- +- return true; ++ public synchronized E[] getRawDataUnchecked() { ++ return ((RefListInner) this.list).getRawDataUnchecked(); + } + +- public boolean add(final E obj) { +- final int count = this.count; +- final int currIndex = this.referenceToIndex.putIfAbsent(obj, count); +- +- if (currIndex != Integer.MIN_VALUE) { +- return false; // already in this list ++ public static class RefListInner extends ReferenceArrayList { ++ public RefListInner(A[] elements) { ++ super(elements, true); + } + +- E[] list = this.references; +- +- if (list.length == count) { +- // resize required +- list = this.references = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative ++ public A[] getRawDataUnchecked() { ++ return this.a; + } +- +- list[count] = obj; +- this.count = count + 1; +- +- return true; +- } +- +- public E getChecked(final int index) { +- if (index < 0 || index >= this.count) { +- throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); +- } +- return this.references[index]; +- } +- +- public E getUnchecked(final int index) { +- return this.references[index]; +- } +- +- public Object[] getRawData() { +- return this.references; +- } +- +- public E[] getRawDataUnchecked() { +- return this.references; +- } +- +- public void clear() { +- this.referenceToIndex.clear(); +- Arrays.fill(this.references, 0, this.count, null); +- this.count = 0; +- } +- +- @Override +- public Iterator iterator() { +- return new Iterator<>() { +- private E lastRet; +- private int current; +- +- @Override +- public boolean hasNext() { +- return this.current < ReferenceList.this.count; +- } +- +- @Override +- public E next() { +- if (this.current >= ReferenceList.this.count) { +- throw new NoSuchElementException(); +- } +- return this.lastRet = ReferenceList.this.references[this.current++]; +- } +- +- @Override +- public void remove() { +- final E lastRet = this.lastRet; +- +- if (lastRet == null) { +- throw new IllegalStateException(); +- } +- this.lastRet = null; +- +- ReferenceList.this.remove(lastRet); +- --this.current; +- } +- }; + } + } ++// DivineMC end - Rewrite ReferenceList diff --git a/patches/work/server/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch b/patches/work/server/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch deleted file mode 100644 index 2ee5bd7..0000000 --- a/patches/work/server/sources/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -+++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java -@@ -19,7 +_,7 @@ - - @Override - public final void addPlayerListener(PlayerAdvancements playerAdvancements, CriterionTrigger.Listener listener) { -- playerAdvancements.criterionData.computeIfAbsent(this, managerx -> Sets.newHashSet()).add(listener); // Paper - fix PlayerAdvancements leak -+ playerAdvancements.criterionData.computeIfAbsent(this, managerx -> Sets.newConcurrentHashSet()).add(listener); // Paper - fix PlayerAdvancements leak // DivineMC - use concurrent set - } - - @Override