diff --git a/divinemc-server/minecraft-patches/features/0001-Rebrand.patch b/divinemc-server/minecraft-patches/features/0001-Rebrand.patch index ceca597..e1498e7 100644 --- a/divinemc-server/minecraft-patches/features/0001-Rebrand.patch +++ b/divinemc-server/minecraft-patches/features/0001-Rebrand.patch @@ -18,7 +18,7 @@ index 394443d00e661715439be1e56dddc129947699a4..480ad57a6b7b74e6b83e9c6ceb69ea1f public CrashReport(String title, Throwable exception) { io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception); // Paper diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index 1485186d4989874ef89c4e83830f26358a43759c..680369af59fd2aa36bf1cf4e28b598854383abe3 100644 +index 1485186d4989874ef89c4e83830f26358a43759c..b48fc9e0b95fe6c8f72c5501b8de374e6ac2e5d6 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java @@ -62,6 +62,14 @@ import org.slf4j.Logger; @@ -36,25 +36,6 @@ index 1485186d4989874ef89c4e83830f26358a43759c..680369af59fd2aa36bf1cf4e28b59885 @SuppressForbidden( reason = "System.out needed before bootstrap" -@@ -114,6 +122,18 @@ public class Main { - org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands = purpurConfiguration.getBoolean("settings.register-minecraft-debug-commands"); // Purpur - register minecraft debug commands - // Purpur end - Add toggle for enchant level clamping - load config files early - -+ // DivineMC start - Server startup settings -+ org.bukkit.configuration.file.YamlConfiguration divinemcConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("divinemc-settings")); -+ boolean divinemcNativeMathEnabled = divinemcConfiguration.getBoolean("settings.chunk-generation.native-acceleration-enabled", true); -+ if (divinemcNativeMathEnabled) { -+ try { -+ Class.forName("org.bxteam.divinemc.math.NativeLoader").getField("lookup").get(null); -+ } catch (Throwable e) { -+ e.printStackTrace(); -+ } -+ } -+ // DivineMC end - Server startup settings -+ - io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper - Bootstrap.bootStrap(); - Bootstrap.validate(); diff --git a/net/minecraft/server/gui/MinecraftServerGui.java b/net/minecraft/server/gui/MinecraftServerGui.java index 614c7d9f673c926562acc8fa3b3788623900db41..33456c7c106abbddf743e1203a6e8122cf10b797 100644 --- a/net/minecraft/server/gui/MinecraftServerGui.java diff --git a/divinemc-server/minecraft-patches/features/0009-Native-Math-Optimizations.patch b/divinemc-server/minecraft-patches/features/0009-Native-Math-Optimizations.patch index 37261ba..2e51677 100644 --- a/divinemc-server/minecraft-patches/features/0009-Native-Math-Optimizations.patch +++ b/divinemc-server/minecraft-patches/features/0009-Native-Math-Optimizations.patch @@ -500,3 +500,71 @@ index 45060882654217eeb9a07357c5149b12fbff02c1..c17f43164009f47050a390eb50688460 } public double maxValue() { +diff --git a/net/minecraft/world/phys/AABB.java b/net/minecraft/world/phys/AABB.java +index c9c6e4e460ad8435f12761704bb9b0284d6aa708..54807bb4b4189ceaded1f78a1a9ab85ce40ab2b1 100644 +--- a/net/minecraft/world/phys/AABB.java ++++ b/net/minecraft/world/phys/AABB.java +@@ -189,13 +189,15 @@ public class AABB { + } + + public AABB intersect(AABB other) { +- double max = Math.max(this.minX, other.minX); +- double max1 = Math.max(this.minY, other.minY); +- double max2 = Math.max(this.minZ, other.minZ); +- double min = Math.min(this.maxX, other.maxX); +- double min1 = Math.min(this.maxY, other.maxY); +- double min2 = Math.min(this.maxZ, other.maxZ); +- return new AABB(max, max1, max2, min, min1, min2); ++ // DivineMC start - Math Optimizations ++ return new AABB( ++ this.minX > other.minX ? this.minX : other.minX, ++ this.minY > other.minY ? this.minY : other.minY, ++ this.minZ > other.minZ ? this.minZ : other.minZ, ++ this.maxX < other.maxX ? this.maxX : other.maxX, ++ this.maxY < other.maxY ? this.maxY : other.maxY, ++ this.maxZ < other.maxZ ? this.maxZ : other.maxZ ++ ); + } + + public AABB minmax(AABB other) { +@@ -227,16 +229,37 @@ public class AABB { + } + + public boolean intersects(AABB other) { +- return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ); ++ // DivineMC start - Math Optimizations ++ return this.minX < other.maxX && ++ this.maxX > other.minX && ++ this.minY < other.maxY && ++ this.maxY > other.minY && ++ this.minZ < other.maxZ && ++ this.maxZ > other.minZ; ++ // DivineMC end - Math Optimizations + } + + public boolean intersects(double x1, double y1, double z1, double x2, double y2, double z2) { +- return this.minX < x2 && this.maxX > x1 && this.minY < y2 && this.maxY > y1 && this.minZ < z2 && this.maxZ > z1; ++ // DivineMC start - Math Optimizations ++ return this.minX < x2 && ++ this.maxX > x1 && ++ this.minY < y2 && ++ this.maxY > y1 && ++ this.minZ < z2 && ++ this.maxZ > z1; ++ // DivineMC end - Math Optimizations + } + + public boolean intersects(Vec3 min, Vec3 max) { + return this.intersects( +- Math.min(min.x, max.x), Math.min(min.y, max.y), Math.min(min.z, max.z), Math.max(min.x, max.x), Math.max(min.y, max.y), Math.max(min.z, max.z) ++ // DivineMC start - Math Optimizations ++ min.x < max.x ? min.x : max.x, ++ min.y < max.y ? min.y : max.y, ++ min.z < max.z ? min.z : max.z, ++ min.x > max.x ? min.x : max.x, ++ min.y > max.y ? min.y : max.y, ++ min.z > max.z ? min.z : max.z ++ // DivineMC end - Math Optimizations + ); + } + diff --git a/divinemc-server/minecraft-patches/features/0012-Chunk-System-optimization.patch b/divinemc-server/minecraft-patches/features/0012-Chunk-System-optimization.patch index 07bd87a..54709a8 100644 --- a/divinemc-server/minecraft-patches/features/0012-Chunk-System-optimization.patch +++ b/divinemc-server/minecraft-patches/features/0012-Chunk-System-optimization.patch @@ -4,8 +4,224 @@ Date: Sat, 1 Feb 2025 00:33:03 +0300 Subject: [PATCH] Chunk System optimization +diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java +index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..b588449cfe766c14a0cf4ea9640b04a51bbcf433 100644 +--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java ++++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java +@@ -59,12 +59,15 @@ public final class NearbyPlayers { + public static final int GENERAL_REALLY_SMALL_AREA_VIEW_DISTANCE_BLOCKS = (GENERAL_REALLY_SMALL_VIEW_DISTANCE << 4); + + private final ServerLevel world; +- private final Reference2ReferenceOpenHashMap players = new Reference2ReferenceOpenHashMap<>(); +- private final Long2ReferenceOpenHashMap byChunk = new Long2ReferenceOpenHashMap<>(); +- private final Long2ReferenceOpenHashMap>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES]; ++ // DivineMC start - Chunk System optimization ++ private final Object callbackLock = new Object(); ++ private final it.unimi.dsi.fastutil.objects.Reference2ReferenceMap players = it.unimi.dsi.fastutil.objects.Reference2ReferenceMaps.synchronize(new Reference2ReferenceOpenHashMap<>()); ++ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap byChunk = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>()); ++ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap>[] directByChunk = new it.unimi.dsi.fastutil.longs.Long2ReferenceMap[TOTAL_MAP_TYPES]; ++ // DivineMC end - Chunk System optimization + { + for (int i = 0; i < this.directByChunk.length; ++i) { +- this.directByChunk[i] = new Long2ReferenceOpenHashMap<>(); ++ this.directByChunk[i] = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>()); // DivineMC - Chunk System optimization + } + } + +@@ -188,7 +191,10 @@ public final class NearbyPlayers { + final ReferenceList list = this.players[idx]; + if (list == null) { + ++this.nonEmptyLists; +- final ReferenceList players = (this.players[idx] = new ReferenceList<>(EMPTY_PLAYERS_ARRAY)); ++ // DivineMC start - Chunk System optimization ++ this.players[idx] = new ReferenceList<>(EMPTY_PLAYERS_ARRAY); ++ final ReferenceList players = this.players[idx]; ++ // DivineMC end - Chunk System optimization + this.nearbyPlayers.directByChunk[idx].put(this.chunkKey, players); + players.add(player); + return; +diff --git a/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java +index 866f38eb0f379ffbe2888023a7d1c290f521a231..08666b4aa1c7663861dc361f60e6f1cc46694521 100644 +--- a/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java ++++ b/ca/spottedleaf/moonrise/patches/blockstate_propertyaccess/util/ZeroCollidingReferenceStateTable.java +@@ -21,13 +21,15 @@ import net.minecraft.world.level.block.state.properties.Property; + + public final class ZeroCollidingReferenceStateTable { + +- private final Int2ObjectOpenHashMap propertyToIndexer; ++ private final it.unimi.dsi.fastutil.ints.Int2ObjectMap propertyToIndexer; // DivineMC - Chunk System optimization + private S[] lookup; + private final Collection> properties; + + public ZeroCollidingReferenceStateTable(final Collection> properties) { +- this.propertyToIndexer = new Int2ObjectOpenHashMap<>(properties.size()); +- this.properties = new ReferenceArrayList<>(properties); ++ // DivineMC start - Chunk System optimization ++ this.propertyToIndexer = it.unimi.dsi.fastutil.ints.Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>(properties.size())); ++ this.properties = it.unimi.dsi.fastutil.objects.ReferenceLists.synchronize(new ReferenceArrayList<>(properties)); ++ // DivineMC end - Chunk System optimization + + final List> sortedProperties = new ArrayList<>(properties); + +@@ -77,11 +79,11 @@ public final class ZeroCollidingReferenceStateTable { + return ret; + } + +- public boolean isLoaded() { ++ public synchronized boolean isLoaded() { // DivineMC - Chunk System optimization + return this.lookup != null; + } + +- public void loadInTable(final Map, Comparable>, S> universe) { ++ public synchronized void loadInTable(final Map, Comparable>, S> universe) { // DivineMC - Chunk System optimization + if (this.lookup != null) { + throw new IllegalStateException(); + } +@@ -117,7 +119,7 @@ public final class ZeroCollidingReferenceStateTable { + return ((PropertyAccess)property).moonrise$getById((int)modded); + } + +- public > S set(final long index, final Property property, final T with) { ++ public synchronized > S set(final long index, final Property property, final T with) { // DivineMC - Chunk System optimization + final int newValueId = ((PropertyAccess)property).moonrise$getIdFor(with); + if (newValueId < 0) { + return null; +@@ -139,7 +141,7 @@ public final class ZeroCollidingReferenceStateTable { + return this.lookup[(int)newIndex]; + } + +- public > S trySet(final long index, final Property property, final T with, final S dfl) { ++ public synchronized > S trySet(final long index, final Property property, final T with, final S dfl) { // DivineMC - Chunk System optimization + final Indexer indexer = this.propertyToIndexer.get(((PropertyAccess)property).moonrise$getId()); + if (indexer == null) { + return dfl; +diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java +index d21ce54ebb5724c04eadf56a2cde701d5eeb5db2..fe0edbb5c91258e620bf42f700aa399bf8b49066 100644 +--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java ++++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java +@@ -40,9 +40,11 @@ public final class ChunkEntitySlices { + + private final EntityCollectionBySection allEntities; + private final EntityCollectionBySection hardCollidingEntities; +- private final Reference2ObjectOpenHashMap, EntityCollectionBySection> entitiesByClass; +- private final Reference2ObjectOpenHashMap, EntityCollectionBySection> entitiesByType; +- private final EntityList entities = new EntityList(); ++ // DivineMC start - Chunk System optimization ++ private final Reference2ObjectMap, EntityCollectionBySection> entitiesByClass; ++ private final Reference2ObjectMap, EntityCollectionBySection> entitiesByType; ++ private final java.util.Set entities = com.google.common.collect.Sets.newConcurrentHashSet(); ++ // DivineMC end - Chunk System optimization + + public FullChunkStatus status; + public final ChunkData chunkData; +@@ -67,8 +69,10 @@ public final class ChunkEntitySlices { + + this.allEntities = new EntityCollectionBySection(this); + this.hardCollidingEntities = new EntityCollectionBySection(this); +- this.entitiesByClass = new Reference2ObjectOpenHashMap<>(); +- this.entitiesByType = new Reference2ObjectOpenHashMap<>(); ++ // DivineMC start - Chunk System optimization ++ this.entitiesByClass = it.unimi.dsi.fastutil.objects.Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>()); ++ this.entitiesByType = it.unimi.dsi.fastutil.objects.Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>()); ++ // DivineMC end - Chunk System optimization + + this.status = status; + this.chunkData = chunkData; +@@ -134,7 +138,7 @@ public final class ChunkEntitySlices { + return null; + } + +- final Entity[] rawData = this.entities.getRawData(); ++ final Entity[] rawData = this.entities.toArray(new Entity[0]); // DivineMC - Chunk System optimization + final List collectedEntities = new ArrayList<>(len); + for (int i = 0; i < len; ++i) { + final Entity entity = rawData[i]; +@@ -153,7 +157,7 @@ public final class ChunkEntitySlices { + // returns true if this chunk has transient entities remaining + public boolean unload() { + final int len = this.entities.size(); +- final Entity[] collectedEntities = Arrays.copyOf(this.entities.getRawData(), len); ++ final Entity[] collectedEntities = Arrays.copyOf(this.entities.toArray(new Entity[0]), len); // DivineMC - Chunk System optimization + + for (int i = 0; i < len; ++i) { + final Entity entity = collectedEntities[i]; +@@ -182,7 +186,7 @@ public final class ChunkEntitySlices { + return new ArrayList<>(); + } + +- final Entity[] rawData = this.entities.getRawData(); ++ final Entity[] rawData = this.entities.toArray(new Entity[0]); // DivineMC - Chunk System optimization + final List collectedEntities = new ArrayList<>(len); + for (int i = 0; i < len; ++i) { + collectedEntities.add(rawData[i]); +@@ -196,7 +200,7 @@ public final class ChunkEntitySlices { + } + + public void mergeInto(final ChunkEntitySlices slices) { +- final Entity[] entities = this.entities.getRawData(); ++ final Entity[] entities = this.entities.toArray(new Entity[0]); // DivineMC - Chunk System optimization + for (int i = 0, size = Math.min(entities.length, this.entities.size()); i < size; ++i) { + final Entity entity = entities[i]; + slices.addEntity(entity, ((ChunkSystemEntity)entity).moonrise$getSectionY()); +@@ -221,11 +225,7 @@ public final class ChunkEntitySlices { + public void updateStatus(final FullChunkStatus status, final EntityLookup lookup) { + this.status = status; + +- final Entity[] entities = this.entities.getRawData(); +- +- for (int i = 0, size = this.entities.size(); i < size; ++i) { +- final Entity entity = entities[i]; +- ++ for (final Entity entity : this.entities) { // DivineMC - Chunk System optimization + final Visibility oldVisibility = EntityLookup.getEntityStatus(entity); + ((ChunkSystemEntity)entity).moonrise$setChunkStatus(status); + final Visibility newVisibility = EntityLookup.getEntityStatus(entity); +@@ -248,10 +248,7 @@ public final class ChunkEntitySlices { + this.hardCollidingEntities.addEntity(entity, sectionIndex); + } + +- for (final Iterator, EntityCollectionBySection>> iterator = +- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) { +- final Reference2ObjectMap.Entry, EntityCollectionBySection> entry = iterator.next(); +- ++ for (final java.util.Map.Entry, EntityCollectionBySection> entry : this.entitiesByClass.entrySet()) { // DivineMC - Chunk System optimization + if (entry.getKey().isInstance(entity)) { + entry.getValue().addEntity(entity, sectionIndex); + } +@@ -282,10 +279,7 @@ public final class ChunkEntitySlices { + this.hardCollidingEntities.removeEntity(entity, sectionIndex); + } + +- for (final Iterator, EntityCollectionBySection>> iterator = +- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) { +- final Reference2ObjectMap.Entry, EntityCollectionBySection> entry = iterator.next(); +- ++ for (final java.util.Map.Entry, EntityCollectionBySection> entry : this.entitiesByClass.entrySet()) { // DivineMC - Chunk System optimization + if (entry.getKey().isInstance(entity)) { + entry.getValue().removeEntity(entity, sectionIndex); + } +@@ -436,13 +430,15 @@ public final class ChunkEntitySlices { + return false; + } + +- final int size = --this.size; ++ // DivineMC start - Chunk System optimization ++ final int lastIdx = --this.size; + final E[] storage = this.storage; +- if (idx != size) { +- System.arraycopy(storage, idx + 1, storage, idx, size - idx); ++ if (idx < lastIdx) { ++ storage[idx] = storage[lastIdx]; + } + +- storage[size] = null; ++ storage[lastIdx] = null; ++ // DivineMC end - Chunk System optimization + + return true; + } diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java -index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f60352f1ea 100644 +index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..76b8d42ae530b59cdaba0583365a557da6b90ede 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java @@ -301,7 +301,7 @@ public final class RegionizedPlayerChunkLoader { @@ -17,7 +233,15 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 TickThread.ensureTickThread("Cannot tick player chunk loader async"); long currTime = System.nanoTime(); for (final ServerPlayer player : new java.util.ArrayList<>(this.world.players())) { -@@ -362,7 +362,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -312,6 +312,7 @@ public final class RegionizedPlayerChunkLoader { + } + loader.update(); // can't invoke plugin logic + loader.updateQueues(currTime); ++ player.connection.resumeFlushing(); // DivineMC - Chunk System optimization + } + } + +@@ -362,7 +363,7 @@ public final class RegionizedPlayerChunkLoader { GENERATED_TICKET_LEVEL, TICK_TICKET_LEVEL }; @@ -26,7 +250,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 { this.chunkTicketStage.defaultReturnValue(CHUNK_TICKET_STAGE_NONE); } -@@ -499,7 +499,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -499,7 +500,7 @@ public final class RegionizedPlayerChunkLoader { } @Override @@ -35,7 +259,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 final long chunk = CoordinateUtils.getChunkKey(chunkX, chunkZ); // note: by the time this is called, the tick cleanup should have ran - so, if the chunk is at // the tick stage it was deemed in range for loading. Thus, we need to move it to generated -@@ -633,7 +633,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -633,7 +634,7 @@ public final class RegionizedPlayerChunkLoader { return Math.max(Math.abs(dx), Math.abs(dz)) <= this.lastTickDistance; } @@ -44,7 +268,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 for (int dz = -radius; dz <= radius; ++dz) { for (int dx = -radius; dx <= radius; ++dx) { if ((dx | dz) == 0) { -@@ -652,19 +652,11 @@ public final class RegionizedPlayerChunkLoader { +@@ -652,19 +653,11 @@ public final class RegionizedPlayerChunkLoader { return true; } @@ -65,7 +289,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 // try to progress chunk loads while (!this.loadingQueue.isEmpty()) { -@@ -691,8 +683,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -691,8 +684,7 @@ public final class RegionizedPlayerChunkLoader { } // try to push more chunk loads @@ -75,7 +299,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 if (maxLoadsThisTick > 0) { final LongArrayList chunks = new LongArrayList(maxLoadsThisTick); for (int i = 0; i < maxLoadsThisTick; ++i) { -@@ -767,9 +758,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -767,9 +759,7 @@ public final class RegionizedPlayerChunkLoader { } // try to push more chunk generations @@ -86,7 +310,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 long ratedGensThisTick = 0L; while (!this.genQueue.isEmpty()) { final long chunkKey = this.genQueue.firstLong(); -@@ -799,8 +788,6 @@ public final class RegionizedPlayerChunkLoader { +@@ -799,8 +789,6 @@ public final class RegionizedPlayerChunkLoader { ); this.generatingQueue.enqueue(chunkKey); } @@ -95,7 +319,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 // try to pull ticking chunks while (!this.tickingQueue.isEmpty()) { -@@ -830,10 +817,10 @@ public final class RegionizedPlayerChunkLoader { +@@ -830,10 +818,10 @@ public final class RegionizedPlayerChunkLoader { } // try to pull sending chunks @@ -108,37 +332,51 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..b3d6b53bd43045a2dd709567e35ae6f6 final long pendingSend = this.sendQueue.firstLong(); final int pendingSendX = CoordinateUtils.getChunkX(pendingSend); final int pendingSendZ = CoordinateUtils.getChunkZ(pendingSend); +@@ -898,9 +886,6 @@ public final class RegionizedPlayerChunkLoader { + + // reset limiters, they will start at a zero allocation + final long time = System.nanoTime(); +- this.chunkLoadTicketLimiter.reset(time); +- this.chunkGenerateTicketLimiter.reset(time); +- this.chunkSendLimiter.reset(time); + + // now we can update + this.update(); +@@ -919,10 +904,10 @@ public final class RegionizedPlayerChunkLoader { + ); + } + +- void update() { ++ synchronized void update() { // DivineMC - Chunk System optimization - synchronized + TickThread.ensureTickThread(this.player, "Cannot update player asynchronously"); + if (this.removed) { +- throw new IllegalStateException("Updating removed player chunk loader"); ++ return; // DivineMC - Chunk System optimization + } + final ViewDistances playerDistances = ((ChunkSystemServerPlayer)this.player).moonrise$getViewDistanceHolder().getViewDistances(); + final ViewDistances worldDistances = ((ChunkSystemServerLevel)this.world).moonrise$getViewDistanceHolder().getViewDistances(); +@@ -1071,7 +1056,7 @@ public final class RegionizedPlayerChunkLoader { + this.flushDelayedTicketOps(); + } + +- void remove() { ++ synchronized void remove() { // DivineMC - Chunk System optimization - synchronized + TickThread.ensureTickThread(this.player, "Cannot add player asynchronously"); + if (this.removed) { + throw new IllegalStateException("Removing removed player chunk loader"); +@@ -1099,7 +1084,7 @@ public final class RegionizedPlayerChunkLoader { + } + + public LongOpenHashSet getSentChunksRaw() { +- return this.sentChunks; ++ return new LongOpenHashSet(this.sentChunks); // DivineMC - Chunk System optimization + } + } + } diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..08c7e25c736fc7a1587bcb2a490845f63001ac8d 100644 +index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..6094b9f2d4a686a4c639c739d182aba7aac430e8 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -145,7 +145,7 @@ public final class ChunkHolderManager { - - public List getOldChunkHolders() { - final List ret = new ArrayList<>(this.chunkHolders.size() + 1); -- for (final Iterator iterator = this.chunkHolders.valueIterator(); iterator.hasNext();) { -+ for (final Iterator iterator = this.chunkHolders.values().iterator(); iterator.hasNext();) { // DivineMC - Chunk System optimization - ret.add(iterator.next().vanillaChunkHolder); - } - return ret; -@@ -153,7 +153,7 @@ public final class ChunkHolderManager { - - public List getChunkHolders() { - final List ret = new ArrayList<>(this.chunkHolders.size() + 1); -- for (final Iterator iterator = this.chunkHolders.valueIterator(); iterator.hasNext();) { -+ for (final Iterator iterator = this.chunkHolders.values().iterator(); iterator.hasNext();) { // DivineMC - Chunk System optimization - ret.add(iterator.next()); - } - return ret; -@@ -168,7 +168,7 @@ public final class ChunkHolderManager { - return new Iterable() { - @Override - public Iterator iterator() { -- final Iterator iterator = ChunkHolderManager.this.chunkHolders.valueIterator(); -+ final Iterator iterator = ChunkHolderManager.this.chunkHolders.values().iterator(); // DivineMC - Chunk System optimization - return new Iterator() { - @Override - public boolean hasNext() { @@ -1208,6 +1208,27 @@ public final class ChunkHolderManager { } } @@ -168,7 +406,7 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..08c7e25c736fc7a1587bcb2a490845f6 ADD, REMOVE, ADD_IF_REMOVED, ADD_AND_REMOVE } diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java -index e4a5fa25ed368fc4662c30934da2963ef446d782..84354d8e2d391ae9e912c782f9a64b426aeb6c3a 100644 +index e4a5fa25ed368fc4662c30934da2963ef446d782..6da0ea5cd83a00578223e0a19f952c917bcbcdae 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java @@ -644,11 +644,19 @@ public final class NewChunkHolder { @@ -191,7 +429,30 @@ index e4a5fa25ed368fc4662c30934da2963ef446d782..84354d8e2d391ae9e912c782f9a64b42 this.scheduler = scheduler; this.vanillaChunkHolder = new ChunkHolder( new ChunkPos(chunkX, chunkZ), ChunkHolderManager.MAX_TICKET_LEVEL, world, -@@ -1214,6 +1222,19 @@ public final class NewChunkHolder { +@@ -790,9 +798,11 @@ public final class NewChunkHolder { + + // note: these are completed with null to indicate that no write occurred + // they are also completed with null to indicate a null write occurred +- private UnloadTask chunkDataUnload; +- private UnloadTask entityDataUnload; +- private UnloadTask poiDataUnload; ++ // DivineMC start - Chunk System optimization ++ private volatile UnloadTask chunkDataUnload; ++ private volatile UnloadTask entityDataUnload; ++ private volatile UnloadTask poiDataUnload; ++ // DivineMC end - Chunk System optimization + + public static final record UnloadTask(CallbackCompletable completable, PrioritisedExecutor.PrioritisedTask task, + LazyRunnable toRun) {} +@@ -1190,6 +1200,7 @@ public final class NewChunkHolder { + for (int dz = -NEIGHBOUR_RADIUS; dz <= NEIGHBOUR_RADIUS; ++dz) { + for (int dx = -NEIGHBOUR_RADIUS; dx <= NEIGHBOUR_RADIUS; ++dx) { + final NewChunkHolder holder = (dx | dz) == 0 ? this : this.scheduler.chunkHolderManager.getChunkHolder(dx + this.chunkX, dz + this.chunkZ); ++ if (holder == null) continue; // DivineMC - Chunk System optimization + if (loaded) { + if (holder.setNeighbourFullLoaded(-dx, -dz)) { + changedFullStatus.add(holder); +@@ -1214,6 +1225,19 @@ public final class NewChunkHolder { private void updateCurrentState(final FullChunkStatus to) { this.currentFullChunkStatus = to; @@ -211,6 +472,46 @@ index e4a5fa25ed368fc4662c30934da2963ef446d782..84354d8e2d391ae9e912c782f9a64b42 } // only to be called on the main thread, no locks need to be held +@@ -1348,11 +1372,11 @@ public final class NewChunkHolder { + return this.requestedGenStatus; + } + +- private final Reference2ObjectOpenHashMap>> statusWaiters = new Reference2ObjectOpenHashMap<>(); ++ private final Map>> statusWaiters = new java.util.concurrent.ConcurrentHashMap<>(); // DivineMC - Chunk System optimization + + void addStatusConsumer(final ChunkStatus status, final Consumer consumer) { + this.statusWaiters.computeIfAbsent(status, (final ChunkStatus keyInMap) -> { +- return new ArrayList<>(4); ++ return new java.util.concurrent.CopyOnWriteArrayList<>(); // DivineMC - Chunk System optimization + }).add(consumer); + } + +@@ -1394,11 +1418,11 @@ public final class NewChunkHolder { + }, Priority.HIGHEST); + } + +- private final Reference2ObjectOpenHashMap>> fullStatusWaiters = new Reference2ObjectOpenHashMap<>(); ++ private final Map>> fullStatusWaiters = new java.util.concurrent.ConcurrentHashMap<>(); + + void addFullStatusConsumer(final FullChunkStatus status, final Consumer consumer) { + this.fullStatusWaiters.computeIfAbsent(status, (final FullChunkStatus keyInMap) -> { +- return new ArrayList<>(4); ++ return new java.util.concurrent.CopyOnWriteArrayList<>(); // DivineMC - Chunk System optimization + }).add(consumer); + } + +diff --git a/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java b/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java +index e97e7d276faf055c89207385d3820debffb06463..4aeb75a2cdcfb4206bab3eee5ad674dd9890e720 100644 +--- a/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java ++++ b/ca/spottedleaf/moonrise/patches/chunk_tick_iteration/ChunkTickConstants.java +@@ -2,6 +2,6 @@ package ca.spottedleaf.moonrise.patches.chunk_tick_iteration; + + public final class ChunkTickConstants { + +- public static final int PLAYER_SPAWN_TRACK_RANGE = 8; ++ public static final int PLAYER_SPAWN_TRACK_RANGE = (int) Math.round(org.bxteam.divinemc.DivineConfig.playerNearChunkDetectionRange / 16.0); // DivineMC - Chunk System optimization + + } diff --git a/net/minecraft/server/level/DistanceManager.java b/net/minecraft/server/level/DistanceManager.java index 5eab6179ce3913cb4e4d424f910ba423faf21c85..189205fbeed7673398fa6f7706864d3723467811 100644 --- a/net/minecraft/server/level/DistanceManager.java diff --git a/divinemc-server/minecraft-patches/features/0014-Some-optimizations.patch b/divinemc-server/minecraft-patches/features/0014-Some-optimizations.patch index acc40aa..7cca5fd 100644 --- a/divinemc-server/minecraft-patches/features/0014-Some-optimizations.patch +++ b/divinemc-server/minecraft-patches/features/0014-Some-optimizations.patch @@ -4,6 +4,27 @@ Date: Sat, 1 Feb 2025 15:59:29 +0300 Subject: [PATCH] Some optimizations +diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java +index 5f752603aa5611ce9d3dd44cc5b70c27ac46a86e..332122c0b700fb743f91f3fed16aade41dceec28 100644 +--- a/net/minecraft/core/MappedRegistry.java ++++ b/net/minecraft/core/MappedRegistry.java +@@ -34,10 +34,12 @@ public class MappedRegistry implements WritableRegistry { + private final ResourceKey> key; + private final ObjectList> byId = new ObjectArrayList<>(256); + private final Reference2IntMap toId = Util.make(new Reference2IntOpenHashMap<>(2048), map -> map.defaultReturnValue(-1)); // Paper - Perf: Use bigger expected size to reduce collisions +- private final Map> byLocation = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions +- private final Map, Holder.Reference> byKey = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions +- private final Map> byValue = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions +- private final Map, RegistrationInfo> registrationInfos = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions ++ // DivineMC start - Some optimizations ++ private final Map> byLocation = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions ++ private final Map, Holder.Reference> byKey = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions ++ private final Map> byValue = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions ++ private final Map, RegistrationInfo> registrationInfos = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions ++ // DivineMC end - Some optimizations + private Lifecycle registryLifecycle; + private final Map, HolderSet.Named> frozenTags = new IdentityHashMap<>(); + MappedRegistry.TagSet allTags = MappedRegistry.TagSet.unbound(); diff --git a/net/minecraft/server/level/ChunkTrackingView.java b/net/minecraft/server/level/ChunkTrackingView.java index bee90335677f7d8b01589ce5cfd81a40fd422886..a5e488d14fd2016ee188b114d0e681562b5b09cc 100644 --- a/net/minecraft/server/level/ChunkTrackingView.java @@ -74,6 +95,141 @@ index 2a708ae0d5bb209650b525e3c56051f8b5655074..762cba15597623f95a242bdd44742d9b } @Override +diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java +index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..5abd899c88683cb79bb8f02e43c4bfbe8563f496 100644 +--- a/net/minecraft/util/CubicSpline.java ++++ b/net/minecraft/util/CubicSpline.java +@@ -254,31 +254,47 @@ public interface CubicSpline> extends ToFloatFun + + @Override + public float apply(C object) { +- float f = this.coordinate.apply(object); +- int i = findIntervalStart(this.locations, f); +- int i1 = this.locations.length - 1; +- if (i < 0) { +- return linearExtend(f, this.locations, this.values.get(0).apply(object), this.derivatives, 0); +- } else if (i == i1) { +- return linearExtend(f, this.locations, this.values.get(i1).apply(object), this.derivatives, i1); ++ // DivineMC start - Some optimizations ++ float point = this.coordinate.apply(object); ++ int rangeForLocation = findIntervalStart(this.locations, point); ++ int last = this.locations.length - 1; ++ if (rangeForLocation < 0) { ++ return linearExtend(point, this.locations, this.values.get(0).apply(object), this.derivatives, 0); ++ } else if (rangeForLocation == last) { ++ return linearExtend(point, this.locations, this.values.get(last).apply(object), this.derivatives, last); + } else { +- float f1 = this.locations[i]; +- float f2 = this.locations[i + 1]; +- float f3 = (f - f1) / (f2 - f1); +- ToFloatFunction toFloatFunction = (ToFloatFunction)this.values.get(i); +- ToFloatFunction toFloatFunction1 = (ToFloatFunction)this.values.get(i + 1); +- float f4 = this.derivatives[i]; +- float f5 = this.derivatives[i + 1]; +- float f6 = toFloatFunction.apply(object); +- float f7 = toFloatFunction1.apply(object); +- float f8 = f4 * (f2 - f1) - (f7 - f6); +- float f9 = -f5 * (f2 - f1) + (f7 - f6); +- return Mth.lerp(f3, f6, f7) + f3 * (1.0F - f3) * Mth.lerp(f3, f8, f9); ++ float loc0 = this.locations[rangeForLocation]; ++ float loc1 = this.locations[rangeForLocation + 1]; ++ float locDist = loc1 - loc0; ++ float k = (point - loc0) / locDist; ++ float n = this.values.get(rangeForLocation).apply(object); ++ float o = this.values.get(rangeForLocation + 1).apply(object); ++ float onDist = o - n; ++ float p = this.derivatives[rangeForLocation] * locDist - onDist; ++ float q = -this.derivatives[rangeForLocation + 1] * locDist + onDist; ++ return Mth.lerp(k, n, o) + k * (1.0F - k) * Mth.lerp(k, p, q); + } ++ // DivineMC end - Some optimizations + } + + private static int findIntervalStart(float[] locations, float start) { +- return Mth.binarySearch(0, locations.length, i -> start < locations[i]) - 1; ++ // DivineMC start - Some optimizations ++ int min = 0; ++ int i = locations.length; ++ ++ while (i > 0) { ++ int j = i / 2; ++ int k = min + j; ++ if (start < locations[k]) { ++ i = j; ++ } else { ++ min = k + 1; ++ i -= j + 1; ++ } ++ } ++ ++ return min - 1; ++ // DivineMC end - Some optimizations + } + + @VisibleForTesting +@@ -313,5 +329,27 @@ public interface CubicSpline> extends ToFloatFun + this.derivatives + ); + } ++ ++ // DivineMC start - Some optimizations ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ Multipoint that = (Multipoint) o; ++ return java.util.Objects.equals(coordinate, that.coordinate()) && java.util.Arrays.equals(locations, that.locations()) && java.util.Objects.equals(values, that.values()) && java.util.Arrays.equals(derivatives, that.derivatives()); ++ } ++ ++ @Override ++ public int hashCode() { ++ int result = 1; ++ ++ result = 31 * result + java.util.Objects.hashCode(coordinate); ++ result = 31 * result + java.util.Arrays.hashCode(locations); ++ result = 31 * result + java.util.Objects.hashCode(values); ++ result = 31 * result + java.util.Arrays.hashCode(derivatives); ++ ++ return result; ++ } ++ // DivineMC end - Some optimizations + } + } +diff --git a/net/minecraft/util/RandomSource.java b/net/minecraft/util/RandomSource.java +index 98a54bc4de251014342cda6d0951b7fea79ce553..cd17a4c7f02abf16fcb3b793c10d8b86d47b7974 100644 +--- a/net/minecraft/util/RandomSource.java ++++ b/net/minecraft/util/RandomSource.java +@@ -12,7 +12,7 @@ public interface RandomSource { + double GAUSSIAN_SPREAD_FACTOR = 2.297; + + static RandomSource create() { +- return create(RandomSupport.generateUniqueSeed()); ++ return createThreadSafe(); // DivineMC - Some optimizations + } + + @Deprecated +@@ -21,7 +21,7 @@ public interface RandomSource { + } + + static RandomSource create(long seed) { +- return new LegacyRandomSource(seed); ++ return new ThreadSafeLegacyRandomSource(seed); // DivineMC - Some optimizations + } + + static RandomSource createNewThreadLocalInstance() { +diff --git a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java +index 15de39fa82c7aea18298509fe9587d027c30cc15..c199f99efe25737602a3565ca6f70177571ff886 100644 +--- a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java ++++ b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java +@@ -15,7 +15,7 @@ public class DebugSampleSubscriptionTracker { + public static final int STOP_SENDING_AFTER_MS = 10000; + private final PlayerList playerList; + private final EnumMap> subscriptions; +- private final Queue subscriptionRequestQueue = new LinkedList<>(); ++ private final java.util.List subscriptionRequestQueue = java.util.Collections.synchronizedList(new LinkedList<>()); // DivineMC - Some optimizations + + public DebugSampleSubscriptionTracker(PlayerList playerList) { + this.playerList = playerList; diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java index bc22d67bba9b1ebb6bef84f5326375100d24461d..4aa5ecf3e7a7f58505de583dba7738dc1a596d72 100644 --- a/net/minecraft/world/entity/Mob.java diff --git a/divinemc-server/minecraft-patches/features/0030-Verify-Minecraft-EULA-earlier.patch b/divinemc-server/minecraft-patches/features/0030-Verify-Minecraft-EULA-earlier.patch index 7ce0984..dd5ff10 100644 --- a/divinemc-server/minecraft-patches/features/0030-Verify-Minecraft-EULA-earlier.patch +++ b/divinemc-server/minecraft-patches/features/0030-Verify-Minecraft-EULA-earlier.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Verify Minecraft EULA earlier diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index 680369af59fd2aa36bf1cf4e28b598854383abe3..d415a175ea1e7b5a5bf1149187247dd7b2619c29 100644 +index b48fc9e0b95fe6c8f72c5501b8de374e6ac2e5d6..44e98037c986dec845613fa24f9664ef1803b96c 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java -@@ -143,7 +143,6 @@ public class Main { +@@ -131,7 +131,6 @@ public class Main { dedicatedServerSettings.forceSave(); RegionFileVersion.configure(dedicatedServerSettings.getProperties().regionFileComression); Path path2 = Paths.get("eula.txt"); @@ -16,7 +16,7 @@ index 680369af59fd2aa36bf1cf4e28b598854383abe3..d415a175ea1e7b5a5bf1149187247dd7 // Paper start - load config files early for access below if needed org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("bukkit-settings")); org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("spigot-settings")); -@@ -166,19 +165,6 @@ public class Main { +@@ -154,19 +153,6 @@ public class Main { return; } diff --git a/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java b/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java index 66ab199..bf31252 100644 --- a/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java +++ b/divinemc-server/src/main/java/org/bxteam/divinemc/DivineConfig.java @@ -174,6 +174,7 @@ public class DivineConfig { public static long chunkDataCacheSoftLimit = 8192L; public static long chunkDataCacheLimit = 32678L; public static int maxViewDistance = 32; + public static int playerNearChunkDetectionRange = 128; public static ChunkSystemAlgorithms chunkWorkerAlgorithm = ChunkSystemAlgorithms.C2ME; public static ChunkTaskPriority chunkTaskPriority = ChunkTaskPriority.EUCLIDEAN_CIRCLE_PATTERN; public static int threadPoolPriority = Thread.NORM_PRIORITY + 1; @@ -201,6 +202,18 @@ public class DivineConfig { chunkDataCacheLimit = getLong("settings.chunk-generation.chunk-data-cache-limit", chunkDataCacheLimit); maxViewDistance = getInt("settings.chunk-generation.max-view-distance", maxViewDistance, "Changes the maximum view distance for the server, allowing clients to have render distances higher than 32"); + playerNearChunkDetectionRange = getInt("settings.chunk-generation.player-near-chunk-detection-range", playerNearChunkDetectionRange, + "In certain checks, like if a player is near a chunk(primarily used for spawning), it checks if the player is within a certain", + "circular range of the chunk. This configuration allows configurability of the distance(in blocks) the player must be to pass the check.", + "", + "This value is used in the calculation 'range/16' to get the distance in chunks any player must be to allow the check to pass.", + "By default, this range is computed to 8, meaning a player must be within an 8 chunk radius of a chunk position to pass.", + "Keep in mind the result is rounded to the nearest whole number."); + + if (playerNearChunkDetectionRange < 0) { + LOGGER.warn("Invalid player near chunk detection range: {}, resetting to default (128)", playerNearChunkDetectionRange); + playerNearChunkDetectionRange = 128; + } chunkWorkerAlgorithm = ChunkSystemAlgorithms.valueOf(getString("settings.chunk-generation.chunk-worker-algorithm", chunkWorkerAlgorithm.name(), "Modifies what algorithm the chunk system will use to define thread counts.", @@ -257,7 +270,7 @@ public class DivineConfig { public static boolean enableRegionizedChunkTicking = false; public static int regionizedChunkTickingExecutorThreadCount = 4; - public static int regionizedChunkTickingExecutorThreadPriority = Thread.NORM_PRIORITY; + public static int regionizedChunkTickingExecutorThreadPriority = Thread.NORM_PRIORITY + 2; private static void regionizedChunkTicking() { enableRegionizedChunkTicking = getBoolean("settings.regionized-chunk-ticking.enable", enableRegionizedChunkTicking, "Enables regionized chunk ticking, similar to like Folia works.",