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

some fixes

This commit is contained in:
NONPLAYT
2025-03-23 00:59:37 +03:00
parent 39d34ee1cb
commit 81a89d8196
7 changed files with 395 additions and 222 deletions

View File

@@ -4,6 +4,38 @@ Date: Fri, 31 Jan 2025 21:50:46 +0300
Subject: [PATCH] Native Math Optimizations
diff --git a/com/mojang/math/OctahedralGroup.java b/com/mojang/math/OctahedralGroup.java
index 11902e7427761746ee098fea3276a34fef0096ba..3ba23fa243f7af712a41316066ca554f1c23b495 100644
--- a/com/mojang/math/OctahedralGroup.java
+++ b/com/mojang/math/OctahedralGroup.java
@@ -112,6 +112,7 @@ public enum OctahedralGroup implements StringRepresentable {
this.transformation = new Matrix3f().scaling(invertX ? -1.0F : 1.0F, invertY ? -1.0F : 1.0F, invertZ ? -1.0F : 1.0F);
this.transformation.mul(permutation.transformation());
this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
+ this.rotate(Direction.UP); // DivineMC - Math Optimizations
}
private BooleanList packInversions() {
diff --git a/com/mojang/math/Transformation.java b/com/mojang/math/Transformation.java
index aa755b8b7f8bc5910322e0c5b520f603da06a85a..e781dea43279aa77cc40a7afd2281c32cc8347a9 100644
--- a/com/mojang/math/Transformation.java
+++ b/com/mojang/math/Transformation.java
@@ -51,6 +51,7 @@ public final class Transformation {
} else {
this.matrix = matrix;
}
+ ensureDecomposed(); // DivineMC - Math Optimizations
}
public Transformation(@Nullable Vector3f translation, @Nullable Quaternionf leftRotation, @Nullable Vector3f scale, @Nullable Quaternionf rightRotation) {
@@ -60,6 +61,7 @@ public final class Transformation {
this.scale = scale != null ? scale : new Vector3f(1.0F, 1.0F, 1.0F);
this.rightRotation = rightRotation != null ? rightRotation : new Quaternionf();
this.decomposed = true;
+ ensureDecomposed(); // DivineMC - Math Optimizations
}
public static Transformation identity() {
diff --git a/net/minecraft/util/Mth.java b/net/minecraft/util/Mth.java
index ae1ab070a93b46a0790eed3feda1d09f5fbe9b25..3befc00c10ce8f29d3ee1ea493c2b220df5eaaea 100644
--- a/net/minecraft/util/Mth.java

View File

@@ -95,131 +95,6 @@ index 866f38eb0f379ffbe2888023a7d1c290f521a231..08666b4aa1c7663861dc361f60e6f1cc
final Indexer indexer = this.propertyToIndexer.get(((PropertyAccess<T>)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<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
- private final Reference2ObjectOpenHashMap<EntityType<?>, EntityCollectionBySection> entitiesByType;
- private final EntityList entities = new EntityList();
+ // DivineMC start - Chunk System optimization
+ private final Reference2ObjectMap<Class<? extends Entity>, EntityCollectionBySection> entitiesByClass;
+ private final Reference2ObjectMap<EntityType<?>, EntityCollectionBySection> entitiesByType;
+ private final java.util.Set<Entity> 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<Entity> 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<Entity> 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<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
- final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
-
+ for (final java.util.Map.Entry<Class<? extends Entity>, 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<Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection>> iterator =
- this.entitiesByClass.reference2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
- final Reference2ObjectMap.Entry<Class<? extends Entity>, EntityCollectionBySection> entry = iterator.next();
-
+ for (final java.util.Map.Entry<Class<? extends Entity>, 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..76b8d42ae530b59cdaba0583365a557da6b90ede 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -374,7 +249,7 @@ index b28083be4384d6c5efbdce898a0e9d7a2f5bd3d3..76b8d42ae530b59cdaba0583365a557d
}
}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..16d3191fb6f90a5ea05090b951e265dff6a489f1 100644
index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..f4fcc3b2676b17ebc276dcb177285f18a0cdfe99 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
@@ -71,36 +71,49 @@ public final class ChunkHolderManager {
@@ -597,8 +472,8 @@ index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..16d3191fb6f90a5ea05090b951e265df
}
+ // DivineMC start - Chunk System optimization
+ public final java.util.Set<Long> blockTickingChunkHolders = java.util.Collections.synchronizedSet(new org.agrona.collections.ObjectHashSet<>(1384, 0.75f));
+ public final java.util.Set<Long> entityTickingChunkHolders = java.util.Collections.synchronizedSet(new org.agrona.collections.ObjectHashSet<>(1384, 0.75f));
+ public final java.util.Set<Long> blockTickingChunkHolders = java.util.Collections.synchronizedSet(new org.agrona.collections.ObjectHashSet<>(10, 0.88f, true));
+ public final java.util.Set<Long> entityTickingChunkHolders = java.util.Collections.synchronizedSet(new org.agrona.collections.ObjectHashSet<>(10, 0.88f, true));
+
+ public void markBlockTicking(@org.jetbrains.annotations.NotNull NewChunkHolder newChunkHolder) {
+ this.blockTickingChunkHolders.add(newChunkHolder.getCachedLongPos());
@@ -746,6 +621,19 @@ index e97e7d276faf055c89207385d3820debffb06463..4aeb75a2cdcfb4206bab3eee5ad674dd
+ 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/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..f94f443f862611f039454d1dc8ff2a4ba5f081d3 100644
--- a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
+++ b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
@@ -325,7 +325,7 @@ public final class SWMRNibbleArray {
}
// operation type: updating
- public boolean updateVisible() {
+ public synchronized boolean updateVisible() { // DivineMC - Chunk System optimization
if (!this.isDirty()) {
return false;
}
diff --git a/net/minecraft/server/level/DistanceManager.java b/net/minecraft/server/level/DistanceManager.java
index 5eab6179ce3913cb4e4d424f910ba423faf21c85..4b1efd53e423bdfe90d5efd472823869fc87e73b 100644
--- a/net/minecraft/server/level/DistanceManager.java
@@ -880,6 +768,19 @@ index 26c8c1e5598daf3550aef05b12218c47bda6618b..94c824ab1457939c425e1f99929d3222
Holder<Biome> getUncachedNoiseBiome(int x, int y, int z);
boolean isClientSide();
diff --git a/net/minecraft/world/level/chunk/ProtoChunk.java b/net/minecraft/world/level/chunk/ProtoChunk.java
index e66239e2da91bd3ddf358d239be796719c0da327..35e9d8cfe12252d3419626f1cefb64d30e20069e 100644
--- a/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -41,7 +41,7 @@ public class ProtoChunk extends ChunkAccess {
@Nullable
private volatile LevelLightEngine lightEngine;
private volatile ChunkStatus status = ChunkStatus.EMPTY;
- private final List<CompoundTag> entities = Lists.newArrayList();
+ private final List<CompoundTag> entities = Collections.synchronizedList(Lists.newArrayList()); // DivineMC - Chunk System optimization
@Nullable
private CarvingMask carvingMask;
@Nullable
diff --git a/net/minecraft/world/level/chunk/storage/IOWorker.java b/net/minecraft/world/level/chunk/storage/IOWorker.java
index 2199a9e2a0141c646d108f2687a27f1d165453c5..c28c2583b257f92207b822a1fdde8f5b7e480992 100644
--- a/net/minecraft/world/level/chunk/storage/IOWorker.java
@@ -936,3 +837,125 @@ index 6ebd1300c2561116b83cb2472ac7939ead36d576..16cd10ab8de69ca3d29c84cf93715645
this.info = info;
this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers
}
diff --git a/net/minecraft/world/level/levelgen/Column.java b/net/minecraft/world/level/levelgen/Column.java
index 4a1df0f8578c9ee5538ed8c94d3c7911f36f83b8..716c2c69843234cdef34339d859babc95ffe318c 100644
--- a/net/minecraft/world/level/levelgen/Column.java
+++ b/net/minecraft/world/level/levelgen/Column.java
@@ -156,7 +156,7 @@ public abstract class Column {
}
public int height() {
- return this.ceiling - this.floor - 1;
+ return net.minecraft.util.Mth.abs(this.ceiling - this.floor - 1); // DivineMC - Chunk System optimization
}
@Override
diff --git a/net/minecraft/world/level/levelgen/WorldgenRandom.java b/net/minecraft/world/level/levelgen/WorldgenRandom.java
index c2d7cd788071e25b8ba2503c30ae80c7a9f353ed..0a2e13c4a3db6517267e1f9e74b6152c73e8351f 100644
--- a/net/minecraft/world/level/levelgen/WorldgenRandom.java
+++ b/net/minecraft/world/level/levelgen/WorldgenRandom.java
@@ -73,7 +73,7 @@ public class WorldgenRandom extends LegacyRandomSource {
}
public static enum Algorithm {
- LEGACY(LegacyRandomSource::new),
+ LEGACY(ThreadSafeLegacyRandomSource::new), // DivineMC - Chunk System optimization
XOROSHIRO(XoroshiroRandomSource::new);
private final LongFunction<RandomSource> constructor;
diff --git a/net/minecraft/world/level/levelgen/feature/stateproviders/RandomizedIntStateProvider.java b/net/minecraft/world/level/levelgen/feature/stateproviders/RandomizedIntStateProvider.java
index f4009671880b00ecec98fe604215e2824e453cdf..c607c801223ea71343ece67b81151e31362f1c31 100644
--- a/net/minecraft/world/level/levelgen/feature/stateproviders/RandomizedIntStateProvider.java
+++ b/net/minecraft/world/level/levelgen/feature/stateproviders/RandomizedIntStateProvider.java
@@ -55,17 +55,21 @@ public class RandomizedIntStateProvider extends BlockStateProvider {
@Override
public BlockState getState(RandomSource random, BlockPos pos) {
- BlockState state = this.source.getState(random, pos);
- if (this.property == null || !state.hasProperty(this.property)) {
- IntegerProperty integerProperty = findProperty(state, this.propertyName);
- if (integerProperty == null) {
- return state;
+ // DivineMC start - Chunk System optimization
+ BlockState blockState = this.source.getState(random, pos);
+ IntegerProperty propertyLocal = this.property;
+ if (propertyLocal == null || !blockState.hasProperty(propertyLocal)) {
+ IntegerProperty intProperty = findProperty(blockState, this.propertyName);
+ if (intProperty == null) {
+ return blockState;
}
- this.property = integerProperty;
+ propertyLocal = intProperty;
+ this.property = intProperty;
}
- return state.setValue(this.property, Integer.valueOf(this.values.sample(random)));
+ return (BlockState)blockState.setValue(propertyLocal, this.values.sample(random));
+ // DivineMC end - Chunk System optimization
}
@Nullable
diff --git a/net/minecraft/world/level/levelgen/structure/ScatteredFeaturePiece.java b/net/minecraft/world/level/levelgen/structure/ScatteredFeaturePiece.java
index d122221deefb218db962e97ba2d958c33d903b8a..56311b439ac22700593d2d31da3a4efe3a519d53 100644
--- a/net/minecraft/world/level/levelgen/structure/ScatteredFeaturePiece.java
+++ b/net/minecraft/world/level/levelgen/structure/ScatteredFeaturePiece.java
@@ -12,7 +12,7 @@ public abstract class ScatteredFeaturePiece extends StructurePiece {
protected final int width;
protected final int height;
protected final int depth;
- protected int heightPosition = -1;
+ protected volatile int heightPosition = -1; // DivineMC - Chunk System optimization - make volatile
protected ScatteredFeaturePiece(StructurePieceType type, int x, int y, int z, int width, int height, int depth, Direction orientation) {
super(type, 0, StructurePiece.makeBoundingBox(x, y, z, orientation, width, height, depth));
diff --git a/net/minecraft/world/level/levelgen/structure/StructureStart.java b/net/minecraft/world/level/levelgen/structure/StructureStart.java
index 4dafa79dd4ec55a443ba3731a79e7cd6e8052f48..8aeab4d773473ad20b1c64295c93d6fcb4ea02a1 100644
--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java
+++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java
@@ -26,7 +26,7 @@ public final class StructureStart {
private final Structure structure;
private final PiecesContainer pieceContainer;
private final ChunkPos chunkPos;
- private int references;
+ private final java.util.concurrent.atomic.AtomicInteger references = new java.util.concurrent.atomic.AtomicInteger(); // DivineMC - Chunk System optimization
@Nullable
private volatile BoundingBox cachedBoundingBox;
@@ -39,7 +39,7 @@ public final class StructureStart {
public StructureStart(Structure structure, ChunkPos chunkPos, int references, PiecesContainer pieceContainer) {
this.structure = structure;
this.chunkPos = chunkPos;
- this.references = references;
+ this.references.set(references); // DivineMC - Chunk System optimization
this.pieceContainer = pieceContainer;
}
@@ -126,7 +126,7 @@ public final class StructureStart {
compoundTag.putString("id", context.registryAccess().lookupOrThrow(Registries.STRUCTURE).getKey(this.structure).toString());
compoundTag.putInt("ChunkX", chunkPos.x);
compoundTag.putInt("ChunkZ", chunkPos.z);
- compoundTag.putInt("references", this.references);
+ compoundTag.putInt("references", this.references.get()); // DivineMC - Chunk System optimization
compoundTag.put("Children", this.pieceContainer.save(context));
return compoundTag;
} else {
@@ -144,15 +144,15 @@ public final class StructureStart {
}
public boolean canBeReferenced() {
- return this.references < this.getMaxReferences();
+ return this.references.get() < this.getMaxReferences(); // DivineMC - Chunk System optimization
}
public void addReference() {
- this.references++;
+ this.references.getAndIncrement(); // DivineMC - Chunk System optimization
}
public int getReferences() {
- return this.references;
+ return this.references.get(); // DivineMC - Chunk System optimization
}
protected int getMaxReferences() {

View File

@@ -4,6 +4,19 @@ Date: Sat, 1 Feb 2025 15:59:29 +0300
Subject: [PATCH] Some optimizations
diff --git a/com/mojang/brigadier/tree/CommandNode.java b/com/mojang/brigadier/tree/CommandNode.java
index 2ae5b80338282ac73c74765fc0729af2d54f6d6c..59c93bbf431836fd29101ff9e7e467d9ea3f5df9 100644
--- a/com/mojang/brigadier/tree/CommandNode.java
+++ b/com/mojang/brigadier/tree/CommandNode.java
@@ -24,7 +24,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
- private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
+ private final Map<String, CommandNode<S>> children = Collections.synchronizedMap(new LinkedHashMap<>()); // DivineMC - Some optimizations
private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
public Predicate<S> requirement; // Paper - public-f
diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java
index 5f752603aa5611ce9d3dd44cc5b70c27ac46a86e..332122c0b700fb743f91f3fed16aade41dceec28 100644
--- a/net/minecraft/core/MappedRegistry.java
@@ -95,6 +108,62 @@ index 2a708ae0d5bb209650b525e3c56051f8b5655074..762cba15597623f95a242bdd44742d9b
}
@Override
diff --git a/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
index f28fbf81a417a678726d3f77b3999054676d522e..fbf17cc11fa8e56c5ada2f0f60c944b6b22591a5 100644
--- a/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
+++ b/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
@@ -52,23 +52,23 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
@Nullable
@Override
- public K byId(int value) {
+ public synchronized K byId(int value) { // DivineMC - Some optimizations
return value >= 0 && value < this.byId.length ? this.byId[value] : null;
}
- private int getValue(int key) {
+ private synchronized int getValue(int key) { // DivineMC - Some optimizations
return key == -1 ? -1 : this.values[key];
}
- public boolean contains(K value) {
+ public synchronized boolean contains(K value) { // DivineMC - Some optimizations
return this.getId(value) != -1;
}
- public boolean contains(int value) {
+ public synchronized boolean contains(int value) { // DivineMC - Some optimizations
return this.byId(value) != null;
}
- public int add(K object) {
+ public synchronized int add(K object) { // DivineMC - Some optimizations
int i = this.nextId();
this.addMapping(object, i);
return i;
@@ -106,7 +106,7 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
// Paper end - optimise palette reads
}
- public void addMapping(K object, int intKey) {
+ public synchronized void addMapping(K object, int intKey) { // DivineMC - Some optimizations
int max = Math.max(intKey, this.size + 1);
if (max >= this.keys.length * 0.8F) {
int i = this.keys.length << 1;
@@ -173,11 +173,11 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
}
@Override
- public Iterator<K> iterator() {
+ public synchronized Iterator<K> iterator() { // DivineMC - Some optimizations
return Iterators.filter(Iterators.forArray(this.byId), Predicates.notNull());
}
- public void clear() {
+ public synchronized void clear() { // DivineMC - Some optimizations
Arrays.fill(this.keys, null);
Arrays.fill(this.byId, null);
this.nextId = 0;
diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java
index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..5abd899c88683cb79bb8f02e43c4bfbe8563f496 100644
--- a/net/minecraft/util/CubicSpline.java
@@ -230,6 +299,19 @@ index 15de39fa82c7aea18298509fe9587d027c30cc15..c199f99efe25737602a3565ca6f70177
public DebugSampleSubscriptionTracker(PlayerList playerList) {
this.playerList = playerList;
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 258cb45f1f959b75c1bcdb130811af2f8fddf07d..40641a649631cfe63b0077d66115aaa525377cf0 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -143,7 +143,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Paper start - Share random for entities to make them more random
- public static RandomSource SHARED_RANDOM = new RandomRandomSource();
+ public static RandomSource SHARED_RANDOM = new net.minecraft.world.level.levelgen.ThreadSafeLegacyRandomSource(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // DivineMC - Some optimizations
// Paper start - replace random
private static final class RandomRandomSource extends ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom {
public RandomRandomSource() {
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index 66f3565b978f2ed91cb2bc3a816f1701c0873c73..b4e19cc65701d5ef94e1cc0a7473225c222725c3 100644
--- a/net/minecraft/world/entity/Mob.java
@@ -313,6 +395,18 @@ index 9641219c190261dea0db5f95f040a705ba0a3ff9..91966607f8f48b56e2c7e9389bd7d8ac
}
}
}
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index 681dec447486138088fe5f705ef4fadab531139f..c34515e0a2954730665acf429dfec6fc3069e7c4 100644
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -198,6 +198,7 @@ public class MapItemSavedData extends SavedData {
}
}
+ mapItemSavedData.setDirty(false); // DivineMC - Some optimizations
return mapItemSavedData;
}
diff --git a/net/minecraft/world/level/storage/DimensionDataStorage.java b/net/minecraft/world/level/storage/DimensionDataStorage.java
index d9a3b5a2e6495b7e22c114506c2bd1e406f58f8f..a6e03345afd6d8a38e06a43c59103209618baa14 100644
--- a/net/minecraft/world/level/storage/DimensionDataStorage.java

View File

@@ -4,39 +4,84 @@ Date: Mon, 3 Mar 2025 19:29:13 +0300
Subject: [PATCH] Async Chunk Sending
diff --git a/net/minecraft/server/network/PlayerChunkSender.java b/net/minecraft/server/network/PlayerChunkSender.java
index 14878690a88fd4de3e2c127086607e6c819c636c..4723ce85ebcd3740245607348a525f292ac1e2f3 100644
--- a/net/minecraft/server/network/PlayerChunkSender.java
+++ b/net/minecraft/server/network/PlayerChunkSender.java
@@ -80,16 +80,21 @@ public class PlayerChunkSender {
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
index 76b8d42ae530b59cdaba0583365a557da6b90ede..4943f57f648d5350e174c995ccb12bf8b2eb700f 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -55,6 +55,8 @@ public final class RegionizedPlayerChunkLoader {
public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY);
public static final int TICK_TICKET_LEVEL = ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL;
// Paper start - Anti-Xray
public static void sendChunk(ServerGamePacketListenerImpl packetListener, ServerLevel level, LevelChunk chunk) {
- final boolean shouldModify = level.chunkPacketBlockController.shouldModify(packetListener.player, chunk);
- packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify));
- // Paper end - Anti-Xray
- // Paper start - PlayerChunkLoadEvent
- if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
- new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
- }
- // Paper end - PlayerChunkLoadEvent
- ChunkPos pos = chunk.getPos();
- DebugPackets.sendPoiPacketsForChunk(level, pos);
+ // DivineMC start - Async Chunk Sending
+ org.bxteam.divinemc.server.chunk.ChunkSendingExecutor.execute(() -> {
+ level.getChunk(chunk.getPos().x, chunk.getPos().z, net.minecraft.world.level.chunk.status.ChunkStatus.FULL); // DivineMC - ensure chunk is loaded
+ final boolean shouldModify = level.chunkPacketBlockController.shouldModify(packetListener.player, chunk);
+ packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify));
+ // Paper end - Anti-Xray
+ // Paper start - PlayerChunkLoadEvent
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
+ public static final org.apache.logging.log4j.Logger LOGGER = org.apache.logging.log4j.LogManager.getLogger("RegionizedPlayerChunkLoader");
+
public static final class ViewDistanceHolder {
private volatile ViewDistances viewDistances;
@@ -426,17 +428,61 @@ public final class RegionizedPlayerChunkLoader {
}
private void sendChunk(final int chunkX, final int chunkZ) {
- if (this.sentChunks.add(CoordinateUtils.getChunkKey(chunkX, chunkZ))) {
- ((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
- .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$addReceivedChunk(this.player);
+ // DivineMC start - Async Chunk Sending
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
+
+ if (!this.sentChunks.add(chunkKey)) return;
- final LevelChunk chunk = ((ChunkSystemLevel)this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
+ final LevelChunk chunk = ((ChunkSystemLevel) this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
+ if (chunk == null) {
+ this.sentChunks.remove(chunkKey);
+ return;
+ }
+ // Paper end - PlayerChunkLoadEvent
+ ChunkPos pos = chunk.getPos();
+ DebugPackets.sendPoiPacketsForChunk(level, pos);
+ }, level);
+ // DivineMC end - Async Chunk Sending
}
private List<LevelChunk> collectChunksToSend(ChunkMap chunkMap, ChunkPos chunkPos) {
+ try {
+ ((ChunkSystemServerLevel) this.world).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkX, chunkZ).vanillaChunkHolder.moonrise$addReceivedChunk(this.player);
PlatformHooks.get().onChunkWatch(this.world, chunk, this.player);
- PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
+ } catch (IllegalStateException e) {
+ this.sentChunks.remove(chunkKey);
return;
}
- throw new IllegalStateException();
+
+ if (org.bxteam.divinemc.DivineConfig.asyncChunkSendingEnabled) {
+ net.minecraft.Util.backgroundExecutor().execute(() -> {
+ try {
+ // Modified from PlayerChunkSender#sendChunk
+ final net.minecraft.server.network.ServerGamePacketListenerImpl connection = this.player.connection;
+ final ServerLevel serverLevel = this.world;
+
+ final net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket packet = new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ chunk, serverLevel.getLightEngine(), null, null,
+ serverLevel.chunkPacketBlockController.shouldModify(this.player, chunk)
+ );
+
+ serverLevel.getServer().execute(() -> {
+ if (this.removed || !this.sentChunks.contains(chunkKey)) return;
+
+ connection.send(packet);
+
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(
+ new org.bukkit.craftbukkit.CraftChunk(chunk),
+ this.player.getBukkitEntity()
+ ).callEvent();
+ }
+
+ net.minecraft.network.protocol.game.DebugPackets.sendPoiPacketsForChunk(serverLevel, chunk.getPos());
+ });
+ } catch (Exception e) {
+ LOGGER.error("Failed to send chunk asynchronously!", e);
+
+ if (!this.removed) this.sentChunks.remove(chunkKey);
+ }
+ });
+ } else {
+ PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
+ }
+ // DivineMC end - Async Chunk Sending
}
private void sendUnloadChunk(final int chunkX, final int chunkZ) {

View File

@@ -570,3 +570,37 @@ index 822ee4a2515ad1d4400bafeaf7177622e88b4aaf..69c44017e7ca2861200c83a16fa9daca
if (!event.callEvent()) {
return itemStack;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
index e4e2e42d0ca25df7fe9f2dd4275610e45fcb2c84..8d0816dcc4159b62e5bbb03e3897b255feb961e6 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
@@ -19,11 +19,28 @@ class CraftAsyncTask extends CraftTask {
@Override
public boolean isSync() {
- return false;
+ return org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && org.bxteam.divinemc.DivineConfig.pwtCompatabilityMode; // DivineMC - Parallel world ticking
}
@Override
public void run() {
+ // DivineMC start - Parallel world ticking
+ if (org.bxteam.divinemc.DivineConfig.enableParallelWorldTicking && org.bxteam.divinemc.DivineConfig.pwtCompatabilityMode) {
+ try {
+ super.run();
+ } catch (final Throwable t) {
+ this.getOwner().getLogger().log(
+ Level.WARNING,
+ String.format(
+ "Plugin %s generated an exception while executing task %s (sync mode)",
+ this.getOwner().getDescription().getFullName(),
+ this.getTaskId()),
+ t);
+ }
+ return;
+ }
+ // DivineMC end - Parallel world ticking
+
final Thread thread = Thread.currentThread();
// Paper start - name threads according to running plugin
final String nameBefore = thread.getName();

View File

@@ -159,6 +159,7 @@ public class DivineConfig {
public static int parallelThreadCount = 4;
public static boolean logContainerCreationStacktraces = false;
public static boolean disableHardThrow = false;
public static boolean pwtCompatabilityMode = false;
private static void parallelWorldTicking() {
enableParallelWorldTicking = getBoolean("settings.parallel-world-ticking.enable", enableParallelWorldTicking,
"Enables Parallel World Ticking, which executes each worlds tick in a separate thread while ensuring that all worlds complete their tick before the next cycle begins.",
@@ -168,6 +169,8 @@ public class DivineConfig {
logContainerCreationStacktraces = getBoolean("settings.parallel-world-ticking.log-container-creation-stacktraces", logContainerCreationStacktraces);
disableHardThrow = getBoolean("settings.parallel-world-ticking.disable-hard-throw", disableHardThrow,
"Disables annoying 'not on main thread' throws. But, THIS IS NOT RECOMMENDED because you SHOULD FIX THE ISSUES THEMSELVES instead of RISKING DATA CORRUPTION! If you lose something, take the blame on yourself.");
pwtCompatabilityMode = getBoolean("settings.parallel-world-ticking.compatability-mode", pwtCompatabilityMode,
"Enables compatibility mode for plugins that are not compatible with Parallel World Ticking. This makes all async tasks run synchronously.");
}
public static boolean nativeAccelerationEnabled = true;
@@ -181,6 +184,7 @@ public class DivineConfig {
public static ChunkTaskPriority chunkTaskPriority = ChunkTaskPriority.EUCLIDEAN_CIRCLE_PATTERN;
public static int threadPoolPriority = Thread.NORM_PRIORITY + 1;
public static boolean enableAsyncNoiseFill = false;
public static boolean asyncChunkSendingEnabled = true;
public static boolean enableSecureSeed = false;
public static boolean smoothBedrockLayer = false;
public static boolean slopesVisualFix = false;
@@ -238,6 +242,8 @@ public class DivineConfig {
"",
"Terrain and biome generation remains the same, but all the ores and structures are generated with 1024-bit seed, instead of the usual 64-bit seed.",
"This seed is almost impossible to crack, and there are no weird links between structures.");
asyncChunkSendingEnabled = getBoolean("settings.chunk-generation.enable-async-chunk-sending", asyncChunkSendingEnabled,
"Makes chunk sending asynchronous, which can significantly reduce main thread load when many players are loading chunks.");
smoothBedrockLayer = getBoolean("settings.chunk-generation.smooth-bedrock-layer", smoothBedrockLayer,
"Smoothens the bedrock layer at the bottom of overworld, and on the top of nether during the world generation.");
@@ -256,20 +262,6 @@ public class DivineConfig {
"modpacks where many structure mods are using very high weight values in their template pools.");
}
public static boolean asyncChunkSendingEnabled = true;
public static int asyncChunkSendingThreadCount = 1;
public static boolean asyncChunkSendingUseVirtualThreads = false;
private static void asyncChunkSending() {
asyncChunkSendingEnabled = getBoolean("settings.async-chunk-sending.enable", asyncChunkSendingEnabled,
"Enables chunk sending runs off-main thread.");
asyncChunkSendingThreadCount = getInt("settings.async-chunk-sending.thread-count", asyncChunkSendingThreadCount,
"Amount of threads to use for async chunk sending. (If use-virtual-threads is enabled, this will be ignored)");
asyncChunkSendingUseVirtualThreads = getBoolean("settings.async-chunk-sending.use-virtual-threads", asyncChunkSendingUseVirtualThreads,
"Similar to the 'virtual-thread' options. This will use the virtual thread executor for chunk sending.");
}
public static boolean enableRegionizedChunkTicking = false;
public static int regionizedChunkTickingExecutorThreadCount = 4;
public static int regionizedChunkTickingExecutorThreadPriority = Thread.NORM_PRIORITY + 2;

View File

@@ -1,47 +0,0 @@
package org.bxteam.divinemc.server.chunk;
import ca.spottedleaf.moonrise.common.util.TickThread;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import org.bxteam.divinemc.DivineConfig;
import org.bxteam.divinemc.util.NamedAgnosticThreadFactory;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChunkSendingExecutor {
private static final ExecutorService SERVICE = DivineConfig.asyncChunkSendingEnabled
? DivineConfig.asyncChunkSendingUseVirtualThreads ?
Executors.newVirtualThreadPerTaskExecutor() :
Executors.newFixedThreadPool(
DivineConfig.asyncChunkSendingThreadCount,
new NamedAgnosticThreadFactory<>("chunk_sending", TickThread::new, Thread.NORM_PRIORITY)
)
: null;
public static void execute(Runnable runnable, ServerLevel level) {
runnable = wrapRunnable(runnable, level);
if (DivineConfig.asyncChunkSendingEnabled) {
SERVICE.submit(runnable);
} else {
runnable.run();
}
}
private static @NotNull Runnable wrapRunnable(Runnable runnable, final ServerLevel level) {
return () -> {
try {
runnable.run();
} catch (Throwable throwable) {
MinecraftServer.LOGGER.warn("Failed to send chunk data! Retrying...");
level.getServer().scheduleOnMain(() -> {
try {
runnable.run();
} catch (Throwable failed) {
MinecraftServer.LOGGER.error("Failed to send chunk data! (2nd attempt). Logging error log", failed);
}
});
}
};
}
}