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

Moonrise and Level Ticking opts (#33)

* moonrise and ticking opts

* additional optimizations

* cleanup

* update entities patch
This commit is contained in:
Artem Ostrasev
2025-08-17 14:56:05 +03:00
committed by GitHub
parent b3c1ee4859
commit b1a98b6f8f
14 changed files with 1500 additions and 272 deletions

View File

@@ -72,7 +72,7 @@
} }
} }
val log4jPlugins = sourceSets.create("log4jPlugins") { val log4jPlugins = sourceSets.create("log4jPlugins") {
@@ -156,10 +_,21 @@ @@ -156,10 +_,22 @@
} }
dependencies { dependencies {
@@ -87,6 +87,7 @@
+ implementation("com.github.luben:zstd-jni:1.5.7-3") + implementation("com.github.luben:zstd-jni:1.5.7-3")
+ implementation("org.lz4:lz4-java:1.8.0") + implementation("org.lz4:lz4-java:1.8.0")
+ implementation("net.openhft:zero-allocation-hashing:0.16") + implementation("net.openhft:zero-allocation-hashing:0.16")
+ implementation("org.agrona:agrona:2.2.4")
+ // DivineMC end - Dependencies + // DivineMC end - Dependencies
+ +
implementation("ca.spottedleaf:concurrentutil:0.0.3") implementation("ca.spottedleaf:concurrentutil:0.0.3")
@@ -175,9 +176,8 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
+ val experimental = rootProject.providers.gradleProperty("experimental").get() // DivineMC - Experimental flag + val experimental = rootProject.providers.gradleProperty("experimental").get() // DivineMC - Experimental flag
attributes( attributes(
- "Main-Class" to "org.bukkit.craftbukkit.Main", "Main-Class" to "org.bukkit.craftbukkit.Main",
- "Implementation-Title" to "Purpur", // Purpur - "Implementation-Title" to "Purpur", // Purpur
+ "Main-Class" to "net.minecraft.server.Main", // DivineMC - Rebrand
+ "Implementation-Title" to "DivineMC", // DivineMC - Rebrand + "Implementation-Title" to "DivineMC", // DivineMC - Rebrand
"Implementation-Version" to implementationVersion, "Implementation-Version" to implementationVersion,
"Implementation-Vendor" to date, "Implementation-Vendor" to date,
@@ -198,12 +198,3 @@
) )
for (tld in setOf("net", "com", "org")) { for (tld in setOf("net", "com", "org")) {
attributes("$tld/bukkit", "Sealed" to true) attributes("$tld/bukkit", "Sealed" to true)
@@ -328,7 +_,7 @@
block: JavaExec.() -> Unit
): TaskProvider<JavaExec> = register<JavaExec>(name) {
group = "runs"
- mainClass.set("org.bukkit.craftbukkit.Main")
+ mainClass.set("net.minecraft.server.Main") // DivineMC - Rebrand
standardInput = System.`in`
workingDir = rootProject.layout.projectDirectory
.dir(providers.gradleProperty("paper.runWorkDir").getOrElse("run"))

View File

@@ -1,18 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Sat, 1 Feb 2025 16:05:57 +0300 Date: Sat, 1 Feb 2025 16:05:57 +0300
Subject: [PATCH] Optimize entity brain Subject: [PATCH] Optimize entities
diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java
index 04875840085541ebfc7014868beec49bb7ab9976..bbfb1de1a03c4208406feb803a2f378db9910556 100644 index 04875840085541ebfc7014868beec49bb7ab9976..caea723a4614d3c406dbce71a392716b7442987c 100644
--- a/net/minecraft/world/entity/AgeableMob.java --- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java +++ b/net/minecraft/world/entity/AgeableMob.java
@@ -125,6 +125,16 @@ public abstract class AgeableMob extends PathfinderMob { @@ -125,6 +125,16 @@ public abstract class AgeableMob extends PathfinderMob {
public void onSyncedDataUpdated(EntityDataAccessor<?> key) { public void onSyncedDataUpdated(EntityDataAccessor<?> key) {
if (DATA_BABY_ID.equals(key)) { if (DATA_BABY_ID.equals(key)) {
this.refreshDimensions(); this.refreshDimensions();
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ if (isBaby()) { + if (isBaby()) {
+ org.bxteam.divinemc.util.entity.SensorHelper.enableSensor(this, net.minecraft.world.entity.ai.sensing.SensorType.NEAREST_ADULT, true); + org.bxteam.divinemc.util.entity.SensorHelper.enableSensor(this, net.minecraft.world.entity.ai.sensing.SensorType.NEAREST_ADULT, true);
+ } else { + } else {
@@ -21,12 +21,204 @@ index 04875840085541ebfc7014868beec49bb7ab9976..bbfb1de1a03c4208406feb803a2f378d
+ this.getBrain().setMemory(net.minecraft.world.entity.ai.memory.MemoryModuleType.NEAREST_VISIBLE_ADULT, java.util.Optional.empty()); + this.getBrain().setMemory(net.minecraft.world.entity.ai.memory.MemoryModuleType.NEAREST_VISIBLE_ADULT, java.util.Optional.empty());
+ } + }
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
} }
super.onSyncedDataUpdated(key); super.onSyncedDataUpdated(key);
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 989043d73af2c719e6c36ac5d4c35e7d31d3410c..6c7f0c04e94eb3fa2f22d2637a1c2abceb1563f4 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1687,6 +1687,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
private void checkInsideBlocks(Vec3 vec3, Vec3 vec31, InsideBlockEffectApplier.StepBasedCollector stepBasedCollector, LongSet set) {
AABB aabb = this.makeBoundingBox(vec31).deflate(1.0E-5F);
+ // DivineMC start - Optimize entities
+ final net.minecraft.world.level.chunk.ChunkAccess[] cachedChunk = new net.minecraft.world.level.chunk.ChunkAccess[] { null };
+ final long[] lastChunkPos = { Long.MIN_VALUE };
+ // DivineMC end - Optimize entities
BlockGetter.forEachBlockIntersectedBetween(
vec3,
vec31,
@@ -1695,7 +1699,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (!this.isAlive()) {
return false;
} else {
- BlockState blockState = this.level().getBlockState(pos);
+ // DivineMC start - Optimize entities
+ final int chunkX = pos.getX() >> 4;
+ final int chunkZ = pos.getZ() >> 4;
+ final long chunkLongPos = ((long) chunkZ << 32) | (chunkX & 0xFFFFFFFFL);
+ if (lastChunkPos[0] != chunkLongPos) {
+ // update cache, this is a different chunk than previous
+ lastChunkPos[0] = chunkLongPos;
+ cachedChunk[0] = this.level.getChunkIfLoaded(chunkX, chunkZ);
+ }
+ net.minecraft.world.level.chunk.ChunkAccess chunk = cachedChunk[0];
+ if (chunk == null) {
+ return true;
+ }
+ BlockState blockState = chunk.getBlockState(pos);
+ // DivineMC end - Optimize entities
if (blockState.isAir()) {
this.debugBlockIntersection(pos, false, false);
return true;
@@ -1738,6 +1756,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean collidedWithFluid(FluidState fluid, BlockPos pos, Vec3 from, Vec3 to) {
+ if (fluid.isEmpty()) return false; // DivineMC - Optimize entities
AABB aabb = fluid.getAABB(this.level(), pos);
return aabb != null && this.collidedWithShapeMovingFrom(from, to, List.of(aabb));
}
diff --git a/net/minecraft/world/entity/InsideBlockEffectApplier.java b/net/minecraft/world/entity/InsideBlockEffectApplier.java
index a7bc5ead2062504ceac95f603bc1ca8d4290bbfd..533c790ce305043f53c76f03a12676c567118a44 100644
--- a/net/minecraft/world/entity/InsideBlockEffectApplier.java
+++ b/net/minecraft/world/entity/InsideBlockEffectApplier.java
@@ -31,68 +31,115 @@ public interface InsideBlockEffectApplier {
public static class StepBasedCollector implements InsideBlockEffectApplier {
private static final InsideBlockEffectType[] APPLY_ORDER = InsideBlockEffectType.values();
- private static final int NO_STEP = -1;
- private final Map<InsideBlockEffectType, Consumer<Entity>> effectsInStep = new java.util.EnumMap<>(InsideBlockEffectType.class); // Paper - track position inside effect was triggered on
- private final Map<InsideBlockEffectType, List<Consumer<Entity>>> beforeEffectsInStep = Util.makeEnumMap(
- InsideBlockEffectType.class, insideBlockEffectType -> new ArrayList<>()
- );
- private final Map<InsideBlockEffectType, List<Consumer<Entity>>> afterEffectsInStep = Util.makeEnumMap(
- InsideBlockEffectType.class, insideBlockEffectType -> new ArrayList<>()
- );
- private final List<Consumer<Entity>> finalEffects = new ArrayList<>();
+ // DivineMC start - Optimize entities
+ private final Consumer<Entity>[] effectsInStep = new Consumer[APPLY_ORDER.length];
+ private final it.unimi.dsi.fastutil.objects.ObjectArrayList<Consumer<Entity>>[] beforeEffectsInStep = new it.unimi.dsi.fastutil.objects.ObjectArrayList[APPLY_ORDER.length];
+ private final it.unimi.dsi.fastutil.objects.ObjectArrayList<Consumer<Entity>>[] afterEffectsInStep = new it.unimi.dsi.fastutil.objects.ObjectArrayList[APPLY_ORDER.length];
+ private final it.unimi.dsi.fastutil.objects.ObjectArrayList<Consumer<Entity>> finalEffects = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
+ // DivineMC end - Optimize entities
private int lastStep = -1;
- public void advanceStep(int step, net.minecraft.core.BlockPos pos) { // Paper - track position inside effect was triggered on
- this.currentBlockPos = pos; // Paper - track position inside effect was triggered on
+ // DivineMC start - Optimize entities
+ public StepBasedCollector() {
+ for (int i = 0; i < APPLY_ORDER.length; i++) {
+ beforeEffectsInStep[i] = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(2);
+ afterEffectsInStep[i] = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(2);
+ }
+ }
+
+ public void advanceStep(int step, net.minecraft.core.BlockPos pos) {
+ this.currentBlockPos = pos;
if (this.lastStep != step) {
this.lastStep = step;
this.flushStep();
}
}
+ // DivineMC end - Optimize entities
public void applyAndClear(Entity entity) {
this.flushStep();
- for (Consumer<Entity> consumer : this.finalEffects) {
+ // DivineMC start - Optimize entities
+ List<Consumer<Entity>> effects = this.finalEffects;
+ int size = effects.size();
+
+ if (size == 0) {
+ this.lastStep = -1;
+ return;
+ }
+
+ if (!entity.isAlive()) {
+ effects.clear();
+ this.lastStep = -1;
+ return;
+ }
+
+ int i = 0;
+ while (i < size - 3) {
+ effects.get(i++).accept(entity);
+ effects.get(i++).accept(entity);
+ effects.get(i++).accept(entity);
+ effects.get(i++).accept(entity);
if (!entity.isAlive()) {
break;
}
+ }
- consumer.accept(entity);
+ if (entity.isAlive()) {
+ for (; i < size; i++) {
+ effects.get(i).accept(entity);
+ if (!entity.isAlive()) {
+ break;
+ }
+ }
}
- this.finalEffects.clear();
+ effects.clear();
+ // DivineMC end - Optimize entities
this.lastStep = -1;
}
private void flushStep() {
- for (InsideBlockEffectType insideBlockEffectType : APPLY_ORDER) {
- List<Consumer<Entity>> list = this.beforeEffectsInStep.get(insideBlockEffectType);
- this.finalEffects.addAll(list);
- list.clear();
- if (this.effectsInStep.remove(insideBlockEffectType) instanceof final Consumer<Entity> recordedEffect) { // Paper - track position inside effect was triggered on - better than null check to avoid diff.
- this.finalEffects.add(recordedEffect); // Paper - track position inside effect was triggered on
+ // DivineMC start - Optimize entities
+ final int len = APPLY_ORDER.length;
+ final Consumer<Entity>[] effectArr = this.effectsInStep;
+ final List<Consumer<Entity>> finalList = this.finalEffects;
+
+ for (int i = 0; i < len; i++) {
+ List<Consumer<Entity>> beforeList = this.beforeEffectsInStep[i];
+ if (!beforeList.isEmpty()) {
+ finalList.addAll(beforeList);
+ beforeList.clear();
}
- List<Consumer<Entity>> list1 = this.afterEffectsInStep.get(insideBlockEffectType);
- this.finalEffects.addAll(list1);
- list1.clear();
+ Consumer<Entity> effect = effectArr[i];
+ if (effect != null) {
+ finalList.add(effect);
+ effectArr[i] = null;
+ }
+
+ List<Consumer<Entity>> afterList = this.afterEffectsInStep[i];
+ if (!afterList.isEmpty()) {
+ finalList.addAll(afterList);
+ afterList.clear();
+ }
}
+ // DivineMC end - Optimize entities
}
@Override
public void apply(InsideBlockEffectType type) {
- this.effectsInStep.put(type, recorded(type)); // Paper - track position inside effect was triggered on
+ effectsInStep[type.ordinal()] = recorded(type); // DivineMC - Optimize entities
}
@Override
public void runBefore(InsideBlockEffectType type, Consumer<Entity> effect) {
- this.beforeEffectsInStep.get(type).add(effect);
+ beforeEffectsInStep[type.ordinal()].add(effect); // DivineMC - Optimize entities
}
@Override
public void runAfter(InsideBlockEffectType type, Consumer<Entity> effect) {
- this.afterEffectsInStep.get(type).add(effect);
+ afterEffectsInStep[type.ordinal()].add(effect); // DivineMC - Optimize entities
}
// Paper start - track position inside effect was triggered on
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da25b9c9327 100644 index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..f839b1429c8ef2a630ae3d6e6a02678161aa5858 100644
--- a/net/minecraft/world/entity/ai/Brain.java --- a/net/minecraft/world/entity/ai/Brain.java
+++ b/net/minecraft/world/entity/ai/Brain.java +++ b/net/minecraft/world/entity/ai/Brain.java
@@ -45,16 +45,75 @@ public class Brain<E extends LivingEntity> { @@ -45,16 +45,75 @@ public class Brain<E extends LivingEntity> {
@@ -35,20 +227,20 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
private static final int SCHEDULE_UPDATE_DELAY = 20; private static final int SCHEDULE_UPDATE_DELAY = 20;
- private final Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newHashMap(); - private final Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newHashMap();
- public final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap(); - public final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap();
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ private Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newConcurrentMap(); + private Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newConcurrentMap();
+ public Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap(); + public Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap();
private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap(); private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap();
private Schedule schedule = Schedule.EMPTY; private Schedule schedule = Schedule.EMPTY;
- private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap(); - private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
+ private Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap(); + private Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap(); private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap();
private Set<Activity> coreActivities = Sets.newHashSet(); private Set<Activity> coreActivities = Sets.newHashSet();
private final Set<Activity> activeActivities = Sets.newHashSet(); private final Set<Activity> activeActivities = Sets.newHashSet();
private Activity defaultActivity = Activity.IDLE; private Activity defaultActivity = Activity.IDLE;
private long lastScheduleUpdate = -9999L; private long lastScheduleUpdate = -9999L;
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ private java.util.ArrayList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> possibleTasks; + private java.util.ArrayList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> possibleTasks;
+ private org.bxteam.divinemc.util.collections.MaskedList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> runningTasks; + private org.bxteam.divinemc.util.collections.MaskedList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> runningTasks;
+ +
@@ -104,7 +296,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
+ } + }
+ this.runningTasks = list; + this.runningTasks = list;
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
public static <E extends LivingEntity> Brain.Provider<E> provider( public static <E extends LivingEntity> Brain.Provider<E> provider(
Collection<? extends MemoryModuleType<?>> memoryTypes, Collection<? extends SensorType<? extends Sensor<? super E>>> sensorTypes Collection<? extends MemoryModuleType<?>> memoryTypes, Collection<? extends SensorType<? extends Sensor<? super E>>> sensorTypes
@@ -112,12 +304,12 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
for (Brain.MemoryValue<?> memoryValue : memoryValues) { for (Brain.MemoryValue<?> memoryValue : memoryValues) {
memoryValue.setMemoryInternal(this); memoryValue.setMemoryInternal(this);
} }
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ this.onTasksChanged(); + this.onTasksChanged();
+ this.memories = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(this.memories); + this.memories = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(this.memories);
+ this.sensors = new it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap<>(this.sensors); + this.sensors = new it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap<>(this.sensors);
+ this.activityRequirements = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.activityRequirements); + this.activityRequirements = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.activityRequirements);
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
} }
public <T> DataResult<T> serializeStart(DynamicOps<T> ops) { public <T> DataResult<T> serializeStart(DynamicOps<T> ops) {
@@ -125,7 +317,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
} }
public <U> void eraseMemory(MemoryModuleType<U> type) { public <U> void eraseMemory(MemoryModuleType<U> type) {
+ if (!this.memories.containsKey(type)) return; // DivineMC - skip if memory does not contain key + if (!this.memories.containsKey(type)) return; // DivineMC - Optimize entities
this.setMemory(type, Optional.empty()); this.setMemory(type, Optional.empty());
} }
@@ -133,7 +325,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
this.setMemoryInternal(memoryType, memory.map(ExpirableValue::of)); this.setMemoryInternal(memoryType, memory.map(ExpirableValue::of));
} }
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
<U> void setMemoryInternal(MemoryModuleType<U> memoryType, Optional<? extends ExpirableValue<?>> memory) { <U> void setMemoryInternal(MemoryModuleType<U> memoryType, Optional<? extends ExpirableValue<?>> memory) {
+ if (memory.isPresent() && this.isEmptyCollection(memory.get().getValue())) { + if (memory.isPresent() && this.isEmptyCollection(memory.get().getValue())) {
+ this.eraseMemory(memoryType); + this.eraseMemory(memoryType);
@@ -163,7 +355,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
+ } + }
+ return oldValue; + return oldValue;
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
+ +
public <U> Optional<U> getMemory(MemoryModuleType<U> type) { public <U> Optional<U> getMemory(MemoryModuleType<U> type) {
Optional<? extends ExpirableValue<?>> optional = this.memories.get(type); Optional<? extends ExpirableValue<?>> optional = this.memories.get(type);
@@ -185,7 +377,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
- } - }
- -
- return list; - return list;
+ return this.getCurrentlyRunningTasks(); // DivineMC - Optimize entity brain + return this.getCurrentlyRunningTasks(); // DivineMC - Optimize entities
} }
public void useDefaultActivity() { public void useDefaultActivity() {
@@ -193,7 +385,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
this.activeActivities.clear(); this.activeActivities.clear();
this.activeActivities.addAll(this.coreActivities); this.activeActivities.addAll(this.coreActivities);
this.activeActivities.add(activity); this.activeActivities.add(activity);
+ this.onPossibleActivitiesChanged(); // DivineMC - Optimize entity brain + this.onPossibleActivitiesChanged(); // DivineMC - Optimize entities
} }
} }
@@ -201,13 +393,13 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
.computeIfAbsent(activity, activity1 -> Sets.newLinkedHashSet()) .computeIfAbsent(activity, activity1 -> Sets.newLinkedHashSet())
.add((BehaviorControl<? super E>)pair.getSecond()); .add((BehaviorControl<? super E>)pair.getSecond());
} }
+ this.onTasksChanged(); // DivineMC - Optimize entity brain + this.onTasksChanged(); // DivineMC - Optimize entities
} }
@VisibleForTesting @VisibleForTesting
public void removeAllBehaviors() { public void removeAllBehaviors() {
this.availableBehaviorsByPriority.clear(); this.availableBehaviorsByPriority.clear();
+ this.onTasksChanged(); // DivineMC - Optimize entity brain + this.onTasksChanged(); // DivineMC - Optimize entities
} }
public boolean isActive(Activity activity) { public boolean isActive(Activity activity) {
@@ -215,7 +407,7 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
} }
} }
+ brain.memoryModCount = this.memoryModCount + 1; // DivineMC - Optimize entity brain + brain.memoryModCount = this.memoryModCount + 1; // DivineMC - Optimize entities
return brain; return brain;
} }
@@ -223,15 +415,15 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) { for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
behaviorControl.doStop(level, owner, gameTime); behaviorControl.doStop(level, owner, gameTime);
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ if (this.runningTasks != null) { + if (this.runningTasks != null) {
+ this.runningTasks.setVisible(behaviorControl, false); + this.runningTasks.setVisible(behaviorControl, false);
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
} }
} }
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
private void startEachNonRunningBehavior(ServerLevel level, E entity) { private void startEachNonRunningBehavior(ServerLevel level, E entity) {
- long gameTime = level.getGameTime(); - long gameTime = level.getGameTime();
- -
@@ -254,33 +446,33 @@ index 99ced3cb7d3d4c7a80d890689d7585fa9acd17f6..9277b5da6065a5500e40727815083da2
} }
} }
} }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
private void tickEachRunningBehavior(ServerLevel level, E entity) { private void tickEachRunningBehavior(ServerLevel level, E entity) {
long gameTime = level.getGameTime(); long gameTime = level.getGameTime();
for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) { for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
behaviorControl.tickOrStop(level, entity, gameTime); behaviorControl.tickOrStop(level, entity, gameTime);
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ if (this.runningTasks != null && behaviorControl.getStatus() != Behavior.Status.RUNNING) { + if (this.runningTasks != null && behaviorControl.getStatus() != Behavior.Status.RUNNING) {
+ this.runningTasks.setVisible(behaviorControl, false); + this.runningTasks.setVisible(behaviorControl, false);
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
} }
} }
diff --git a/net/minecraft/world/entity/ai/behavior/Behavior.java b/net/minecraft/world/entity/ai/behavior/Behavior.java diff --git a/net/minecraft/world/entity/ai/behavior/Behavior.java b/net/minecraft/world/entity/ai/behavior/Behavior.java
index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..f367012ebcc4d06ac868bbc1733bee39ad2d67b1 100644 index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..02508662c722a515cfd78f872c8ba8bbffd8b6fb 100644
--- a/net/minecraft/world/entity/ai/behavior/Behavior.java --- a/net/minecraft/world/entity/ai/behavior/Behavior.java
+++ b/net/minecraft/world/entity/ai/behavior/Behavior.java +++ b/net/minecraft/world/entity/ai/behavior/Behavior.java
@@ -14,6 +14,10 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro @@ -14,6 +14,10 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
private long endTimestamp; private long endTimestamp;
private final int minDuration; private final int minDuration;
private final int maxDuration; private final int maxDuration;
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ private long cachedMemoryModCount = -1; + private long cachedMemoryModCount = -1;
+ private boolean cachedHasRequiredMemoryState; + private boolean cachedHasRequiredMemoryState;
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
private final String configKey; // Paper - configurable behavior tick rate and timings private final String configKey; // Paper - configurable behavior tick rate and timings
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> entryCondition) { public Behavior(Map<MemoryModuleType<?>, MemoryStatus> entryCondition) {
@@ -289,7 +481,7 @@ index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..f367012ebcc4d06ac868bbc1733bee39
this.minDuration = minDuration; this.minDuration = minDuration;
this.maxDuration = maxDuration; this.maxDuration = maxDuration;
- this.entryCondition = entryCondition; - this.entryCondition = entryCondition;
+ this.entryCondition = new it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap<>(entryCondition); // DivineMC - Optimize entity brain - Use fastutil + this.entryCondition = new it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap<>(entryCondition); // DivineMC - Optimize entities - Use fastutil
// Paper start - configurable behavior tick rate and timings // Paper start - configurable behavior tick rate and timings
String key = io.papermc.paper.util.MappingEnvironment.reobf() ? io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()) : this.getClass().getName(); String key = io.papermc.paper.util.MappingEnvironment.reobf() ? io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()) : this.getClass().getName();
int lastSeparator = key.lastIndexOf('.'); int lastSeparator = key.lastIndexOf('.');
@@ -303,7 +495,7 @@ index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..f367012ebcc4d06ac868bbc1733bee39
- MemoryStatus memoryStatus = entry.getValue(); - MemoryStatus memoryStatus = entry.getValue();
- if (!owner.getBrain().checkMemory(memoryModuleType, memoryStatus)) { - if (!owner.getBrain().checkMemory(memoryModuleType, memoryStatus)) {
- return false; - return false;
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ public boolean hasRequiredMemories(E entity) { + public boolean hasRequiredMemories(E entity) {
+ net.minecraft.world.entity.ai.Brain<?> brain = entity.getBrain(); + net.minecraft.world.entity.ai.Brain<?> brain = entity.getBrain();
+ long modCount = brain.getMemoryModCount(); + long modCount = brain.getMemoryModCount();
@@ -323,24 +515,24 @@ index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..f367012ebcc4d06ac868bbc1733bee39
- return true; - return true;
+ return this.cachedHasRequiredMemoryState = true; + return this.cachedHasRequiredMemoryState = true;
} }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
public static enum Status { public static enum Status {
STOPPED, STOPPED,
diff --git a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java diff --git a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
index 977afa268838304abdb34be253ca36ac1c22e99f..ff04ea295b70583137deb8babe5e75ebc755f697 100644 index 977afa268838304abdb34be253ca36ac1c22e99f..9fdb2ce7b72d0a10c2148027990a0048ca93f976 100644
--- a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java --- a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
+++ b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java +++ b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
@@ -119,6 +119,12 @@ public class LongJumpToRandomPos<E extends Mob> extends Behavior<E> { @@ -119,6 +119,12 @@ public class LongJumpToRandomPos<E extends Mob> extends Behavior<E> {
int x = blockPos.getX(); int x = blockPos.getX();
int y = blockPos.getY(); int y = blockPos.getY();
int z = blockPos.getZ(); int z = blockPos.getZ();
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ if (this.maxLongJumpWidth < 128 && this.maxLongJumpHeight < 128) { + if (this.maxLongJumpWidth < 128 && this.maxLongJumpHeight < 128) {
+ this.jumpCandidates = org.bxteam.divinemc.util.collections.LongJumpChoiceList.forCenter(blockPos, (byte) this.maxLongJumpWidth, (byte) this.maxLongJumpHeight); + this.jumpCandidates = org.bxteam.divinemc.util.collections.LongJumpChoiceList.forCenter(blockPos, (byte) this.maxLongJumpWidth, (byte) this.maxLongJumpHeight);
+ return; + return;
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
this.jumpCandidates = BlockPos.betweenClosedStream( this.jumpCandidates = BlockPos.betweenClosedStream(
x - this.maxLongJumpWidth, x - this.maxLongJumpWidth,
y - this.maxLongJumpHeight, y - this.maxLongJumpHeight,
@@ -348,7 +540,7 @@ index 977afa268838304abdb34be253ca36ac1c22e99f..ff04ea295b70583137deb8babe5e75eb
} }
} }
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
protected Optional<LongJumpToRandomPos.PossibleJump> getJumpCandidate(ServerLevel level) { protected Optional<LongJumpToRandomPos.PossibleJump> getJumpCandidate(ServerLevel level) {
- Optional<LongJumpToRandomPos.PossibleJump> randomItem = WeightedRandom.getRandomItem( - Optional<LongJumpToRandomPos.PossibleJump> randomItem = WeightedRandom.getRandomItem(
- level.random, this.jumpCandidates, LongJumpToRandomPos.PossibleJump::weight - level.random, this.jumpCandidates, LongJumpToRandomPos.PossibleJump::weight
@@ -375,6 +567,23 @@ index 977afa268838304abdb34be253ca36ac1c22e99f..ff04ea295b70583137deb8babe5e75eb
} }
private boolean isAcceptableLandingPosition(ServerLevel level, E entity, BlockPos pos) { private boolean isAcceptableLandingPosition(ServerLevel level, E entity, BlockPos pos) {
diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..dfc62772d5617f0dce72b45a1bebf1b2f051efd5 100644
--- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
+++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
@@ -17,10 +17,10 @@ public class NearestLivingEntitySensor<T extends LivingEntity> extends Sensor<T>
protected void doTick(ServerLevel level, T entity) {
double attributeValue = entity.getAttributeValue(Attributes.FOLLOW_RANGE);
AABB aabb = entity.getBoundingBox().inflate(attributeValue, attributeValue, attributeValue);
- List<LivingEntity> entitiesOfClass = level.getEntitiesOfClass(
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<LivingEntity> entitiesOfClass = (it.unimi.dsi.fastutil.objects.ObjectArrayList<LivingEntity>) level.getEntitiesOfClass( // DivineMC - Optimize collections
LivingEntity.class, aabb, matchableEntity -> matchableEntity != entity && matchableEntity.isAlive()
);
- entitiesOfClass.sort(Comparator.comparingDouble(entity::distanceToSqr));
+ entitiesOfClass.unstableSort(Comparator.comparingDouble(entity::distanceToSqr)); // DivineMC - Optimize collections
Brain<?> brain = entity.getBrain();
brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, entitiesOfClass);
brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, new NearestVisibleLivingEntities(level, entity, entitiesOfClass));
diff --git a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java b/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java diff --git a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java b/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java
index 24d1928445b5571e040a2b12d5c82e77a880d9bd..dac0a23aebf2dea1972c07d5c82079da7c9837ac 100644 index 24d1928445b5571e040a2b12d5c82e77a880d9bd..dac0a23aebf2dea1972c07d5c82079da7c9837ac 100644
--- a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java --- a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java
@@ -404,38 +613,38 @@ index 24d1928445b5571e040a2b12d5c82e77a880d9bd..dac0a23aebf2dea1972c07d5c82079da
private boolean isVillagerBaby(LivingEntity livingEntity) { private boolean isVillagerBaby(LivingEntity livingEntity) {
return livingEntity.getType() == EntityType.VILLAGER && livingEntity.isBaby(); return livingEntity.getType() == EntityType.VILLAGER && livingEntity.isBaby();
diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java
index 70b32e0d06f9b8b7999df5fdfd773c09394e23fb..997cff138d5c99b1be9224cb3c96bdfeeb79915a 100644 index 70b32e0d06f9b8b7999df5fdfd773c09394e23fb..188c233721d7a98c8a437dd5bd155b1f3de9134e 100644
--- a/net/minecraft/world/entity/animal/goat/Goat.java --- a/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/net/minecraft/world/entity/animal/goat/Goat.java +++ b/net/minecraft/world/entity/animal/goat/Goat.java
@@ -100,6 +100,13 @@ public class Goat extends Animal { @@ -100,6 +100,13 @@ public class Goat extends Animal {
this.getNavigation().setCanFloat(true); this.getNavigation().setCanFloat(true);
this.setPathfindingMalus(PathType.POWDER_SNOW, -1.0F); this.setPathfindingMalus(PathType.POWDER_SNOW, -1.0F);
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F); this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
+ // DivineMC start - Optimize entity brain + // DivineMC start - Optimize entities
+ if (!this.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM)) { + if (!this.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM)) {
+ org.bxteam.divinemc.util.entity.SensorHelper.disableSensor(this, SensorType.NEAREST_ITEMS); + org.bxteam.divinemc.util.entity.SensorHelper.disableSensor(this, SensorType.NEAREST_ITEMS);
+ } else if (net.minecraft.SharedConstants.IS_RUNNING_IN_IDE) { + } else if (net.minecraft.SharedConstants.IS_RUNNING_IN_IDE) {
+ throw new IllegalStateException("Goat Entity has a nearest visible wanted item memory module! This patch(Optimize-Brain, Goat.java changes) should probably be removed permanently!"); + throw new IllegalStateException("Goat Entity has a nearest visible wanted item memory module! This patch(Optimize-Brain, Goat.java changes) should probably be removed permanently!");
+ } + }
+ // DivineMC end - Optimize entity brain + // DivineMC end - Optimize entities
} }
public ItemStack createHorn() { public ItemStack createHorn() {
diff --git a/net/minecraft/world/entity/schedule/Activity.java b/net/minecraft/world/entity/schedule/Activity.java diff --git a/net/minecraft/world/entity/schedule/Activity.java b/net/minecraft/world/entity/schedule/Activity.java
index 5a143bb6fabba3dc4e2272afb0be636d5722ea22..f17cc8135121f1a97f13bf83a0205e7fcb08b431 100644 index 5a143bb6fabba3dc4e2272afb0be636d5722ea22..133a51ed45500aba7b0bc4a7acb19731a524d8c1 100644
--- a/net/minecraft/world/entity/schedule/Activity.java --- a/net/minecraft/world/entity/schedule/Activity.java
+++ b/net/minecraft/world/entity/schedule/Activity.java +++ b/net/minecraft/world/entity/schedule/Activity.java
@@ -32,10 +32,12 @@ public class Activity { @@ -32,10 +32,12 @@ public class Activity {
public static final Activity DIG = register("dig"); public static final Activity DIG = register("dig");
private final String name; private final String name;
private final int hashCode; private final int hashCode;
+ public final int id; // DivineMC - Cache registry ID + public final int id; // DivineMC - Optimize entities - cache registry ID
- private Activity(String name) { - private Activity(String name) {
+ private Activity(String name, int id) { + private Activity(String name, int id) {
this.name = name; this.name = name;
this.hashCode = name.hashCode(); this.hashCode = name.hashCode();
+ this.id = id; // DivineMC - Cache registry ID + this.id = id; // DivineMC - Optimize entities - cache registry ID
} }
public String getName() { public String getName() {
@@ -444,7 +653,7 @@ index 5a143bb6fabba3dc4e2272afb0be636d5722ea22..f17cc8135121f1a97f13bf83a0205e7f
private static Activity register(String key) { private static Activity register(String key) {
- return Registry.register(BuiltInRegistries.ACTIVITY, key, new Activity(key)); - return Registry.register(BuiltInRegistries.ACTIVITY, key, new Activity(key));
+ return Registry.register(BuiltInRegistries.ACTIVITY, key, new Activity(key, BuiltInRegistries.ACTIVITY.size())); // DivineMC - Cache registry ID + return Registry.register(BuiltInRegistries.ACTIVITY, key, new Activity(key, BuiltInRegistries.ACTIVITY.size())); // DivineMC - Optimize entities - cache registry ID
} }
@Override @Override

View File

@@ -640,10 +640,10 @@ index f9e7532f86122a379692561a639a209a126e8bba..839f6b7696ef85314da185bedba7cfc5
if (isLocatorBarEnabledFor(player)) { if (isLocatorBarEnabledFor(player)) {
if (!connection.isBroken()) { if (!connection.isBroken()) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 461abfac4749ca06b613cfee9e1ad9e6961299df..137b786bf15bbbe52f22bd9e25c1ef3c0d04e642 100644 index 6963be899ac218bd091e73b72c9ccef82e33de36..85da5aec677d84aea005449d97c1ee3ca616e2e4 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -3461,14 +3461,34 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -3480,14 +3480,34 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (this.portalProcess != null) { if (this.portalProcess != null) {
if (this.portalProcess.processPortalTeleportation(serverLevel, this, this.canUsePortal(false))) { if (this.portalProcess.processPortalTeleportation(serverLevel, this, this.canUsePortal(false))) {
this.setPortalCooldown(); this.setPortalCooldown();
@@ -684,7 +684,7 @@ index 461abfac4749ca06b613cfee9e1ad9e6961299df..137b786bf15bbbe52f22bd9e25c1ef3c
} else if (this.portalProcess.hasExpired()) { } else if (this.portalProcess.hasExpired()) {
this.portalProcess = null; this.portalProcess = null;
} }
@@ -4045,6 +4065,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4064,6 +4084,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
private Entity teleportCrossDimension(ServerLevel oldLevel, ServerLevel newLevel, TeleportTransition teleportTransition) { private Entity teleportCrossDimension(ServerLevel oldLevel, ServerLevel newLevel, TeleportTransition teleportTransition) {

View File

@@ -23,7 +23,7 @@ index 7ca147cf9da67c399806056e5092841f7ca32321..a6bf257ca93e4b3819b65b4ef4ba71d9
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1); double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) { if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 0915a08bc8d2dd38ade01e31c34abd69e1abd365..b720230c4bef699fa1b60d949c47aa4c193a24db 100644 index 85da5aec677d84aea005449d97c1ee3ca616e2e4..4c9e0eaedad3f4a372b48580cbe9b03fe2f8c037 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -145,7 +145,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter; @@ -145,7 +145,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
@@ -35,7 +35,7 @@ index 0915a08bc8d2dd38ade01e31c34abd69e1abd365..b720230c4bef699fa1b60d949c47aa4c
public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur - Configurable entity base attributes
// CraftBukkit start // CraftBukkit start
private static final int CURRENT_LEVEL = 2; private static final int CURRENT_LEVEL = 2;
@@ -5476,4 +5476,47 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -5495,4 +5495,47 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return false; return false;
} }
// Purpur end - Ridables // Purpur end - Ridables

View File

@@ -105,7 +105,7 @@ index 0ad18866c323308ad9b87322932e03a283f740b1..386fdc23b35675a7db66d16bf2a8a6dd
private void tickPassenger(Entity ridingEntity, Entity passengerEntity, final boolean isActive) { // Paper - EAR 2 private void tickPassenger(Entity ridingEntity, Entity passengerEntity, final boolean isActive) { // Paper - EAR 2
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index b720230c4bef699fa1b60d949c47aa4c193a24db..c671370a0addb31bc8ca7d7fa642d3b53b5c00ee 100644 index 4c9e0eaedad3f4a372b48580cbe9b03fe2f8c037..d947bff42cbf7aaac0b7f62bc78c239a5f6af381 100644
--- a/net/minecraft/world/entity/Entity.java --- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java
@@ -1111,29 +1111,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -1111,29 +1111,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -152,7 +152,7 @@ index b720230c4bef699fa1b60d949c47aa4c193a24db..c671370a0addb31bc8ca7d7fa642d3b5
} }
private void applyMovementEmissionAndPlaySound(Entity.MovementEmission movementEmission, Vec3 movement, BlockPos pos, BlockState state) { private void applyMovementEmissionAndPlaySound(Entity.MovementEmission movementEmission, Vec3 movement, BlockPos pos, BlockState state) {
@@ -4950,9 +4924,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4969,9 +4943,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public void setDeltaMovement(Vec3 deltaMovement) { public void setDeltaMovement(Vec3 deltaMovement) {
@@ -162,7 +162,7 @@ index b720230c4bef699fa1b60d949c47aa4c193a24db..c671370a0addb31bc8ca7d7fa642d3b5
} }
public void addDeltaMovement(Vec3 addend) { public void addDeltaMovement(Vec3 addend) {
@@ -5050,9 +5022,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -5069,9 +5041,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
// Paper end - Block invalid positions and bounding box // Paper end - Block invalid positions and bounding box
if (this.position.x != x || this.position.y != y || this.position.z != z) { if (this.position.x != x || this.position.y != y || this.position.z != z) {

View File

@@ -18,10 +18,10 @@ index 6d1fe8028739145b11fce98ad62b2f8044299548..9f086ded18d1fc8850877c6be113d880
// note: vanilla does not subtract 0.5 but the result is (luckily!) the same // note: vanilla does not subtract 0.5 but the result is (luckily!) the same
public static final int NARROW_SPAWN_TRACK_RANGE = (int)Math.floor(((double)PLAYER_SPAWN_TRACK_RANGE / Math.sqrt(2.0)) - 0.5); public static final int NARROW_SPAWN_TRACK_RANGE = (int)Math.floor(((double)PLAYER_SPAWN_TRACK_RANGE / Math.sqrt(2.0)) - 0.5);
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 038d75aa39a158b65887c81f2687cb3c8140a6e2..3ca2f56cb31d41e88eb2a3e59c3749fbdef7c85e 100644 index a6bf257ca93e4b3819b65b4ef4ba71d9e2b40933..de7800b46f7e8c68f24de8476032f2179edc4797 100644
--- a/net/minecraft/server/level/ChunkMap.java --- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java
@@ -824,10 +824,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -822,10 +822,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
final ServerPlayer[] raw = players.getRawDataUnchecked(); final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size(); final int len = players.size();
@@ -35,7 +35,7 @@ index 038d75aa39a158b65887c81f2687cb3c8140a6e2..3ca2f56cb31d41e88eb2a3e59c3749fb
if (ret == null) { if (ret == null) {
ret = new ArrayList<>(len - i); ret = new ArrayList<>(len - i);
ret.add(player); ret.add(player);
@@ -1222,6 +1222,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -1220,6 +1220,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
for (int i = 0; i < playersLength; ++i) { // DivineMC - Multithreaded tracker for (int i = 0; i < playersLength; ++i) { // DivineMC - Multithreaded tracker
final ServerPlayer player = playersRaw[i]; final ServerPlayer player = playersRaw[i];

View File

@@ -37,7 +37,7 @@ index 7e31c5c8659d24948fd45a2d6ee7bdeca6027d27..95221434fd8eef388f0308b72af3f934
protected NonNullList(List<E> list, @Nullable E defaultValue) { protected NonNullList(List<E> list, @Nullable E defaultValue) {
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index a6bf257ca93e4b3819b65b4ef4ba71d9e2b40933..038d75aa39a158b65887c81f2687cb3c8140a6e2 100644 index de7800b46f7e8c68f24de8476032f2179edc4797..3ca2f56cb31d41e88eb2a3e59c3749fbdef7c85e 100644
--- a/net/minecraft/server/level/ChunkMap.java --- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java
@@ -132,8 +132,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -132,8 +132,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -53,23 +53,19 @@ index a6bf257ca93e4b3819b65b4ef4ba71d9e2b40933..038d75aa39a158b65887c81f2687cb3c
// Paper - rewrite chunk system // Paper - rewrite chunk system
public int serverViewDistance; public int serverViewDistance;
public final WorldGenContext worldGenContext; // Paper - public public final WorldGenContext worldGenContext; // Paper - public
diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java diff --git a/net/minecraft/stats/StatType.java b/net/minecraft/stats/StatType.java
index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..dfc62772d5617f0dce72b45a1bebf1b2f051efd5 100644 index e42b894f0bdecd9417c3d53bfc172cd0726340bc..0865554f79536dc324766346223413c670348600 100644
--- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java --- a/net/minecraft/stats/StatType.java
+++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +++ b/net/minecraft/stats/StatType.java
@@ -17,10 +17,10 @@ public class NearestLivingEntitySensor<T extends LivingEntity> extends Sensor<T> @@ -11,7 +11,7 @@ import net.minecraft.network.codec.StreamCodec;
protected void doTick(ServerLevel level, T entity) {
double attributeValue = entity.getAttributeValue(Attributes.FOLLOW_RANGE); public class StatType<T> implements Iterable<Stat<T>> {
AABB aabb = entity.getBoundingBox().inflate(attributeValue, attributeValue, attributeValue); private final Registry<T> registry;
- List<LivingEntity> entitiesOfClass = level.getEntitiesOfClass( - private final Map<T, Stat<T>> map = new IdentityHashMap<>();
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<LivingEntity> entitiesOfClass = (it.unimi.dsi.fastutil.objects.ObjectArrayList<LivingEntity>) level.getEntitiesOfClass( // DivineMC - Optimize collections + private final Map<T, Stat<T>> map = new it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap<>(); // DivineMC - Optimize collections
LivingEntity.class, aabb, matchableEntity -> matchableEntity != entity && matchableEntity.isAlive() private final Component displayName;
); private final StreamCodec<RegistryFriendlyByteBuf, Stat<T>> streamCodec;
- entitiesOfClass.sort(Comparator.comparingDouble(entity::distanceToSqr));
+ entitiesOfClass.unstableSort(Comparator.comparingDouble(entity::distanceToSqr)); // DivineMC - Optimize collections
Brain<?> brain = entity.getBrain();
brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, entitiesOfClass);
brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, new NearestVisibleLivingEntities(level, entity, entitiesOfClass));
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 66ba223dacefb3531c46b144c4499b2b2285eafe..0b7f9af0c4e43115878769043ebd06a09ccdf059 100644 index 66ba223dacefb3531c46b144c4499b2b2285eafe..0b7f9af0c4e43115878769043ebd06a09ccdf059 100644
--- a/net/minecraft/world/level/Level.java --- a/net/minecraft/world/level/Level.java
@@ -92,16 +88,16 @@ index 66ba223dacefb3531c46b144c4499b2b2285eafe..0b7f9af0c4e43115878769043ebd06a0
((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getHardCollidingEntities(entity, box, ret, predicate); ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getHardCollidingEntities(entity, box, ret, predicate);
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java diff --git a/net/minecraft/world/level/chunk/ProtoChunk.java b/net/minecraft/world/level/chunk/ProtoChunk.java
index 24f13e2b0b694ff4dd01aeea876ef874f1828304..1135aa373a631cb90b6c0c75fd3590bcbefd4a4c 100644 index aa085d8a78a3fb40a214e4b152ab04d9a409f76f..5ed1a8b6ac025d03fdeb408a6eaa00320087f690 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java --- a/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/ProtoChunk.java
@@ -75,7 +75,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @@ -46,7 +46,7 @@ public class ProtoChunk extends ChunkAccess {
return "<null>"; @Nullable
} private volatile LevelLightEngine lightEngine;
}; private volatile ChunkStatus status = ChunkStatus.EMPTY;
- private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = Maps.newHashMap(); - private final List<CompoundTag> entities = Lists.newArrayList();
+ private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // DivineMC - Optimize collections + private final List<CompoundTag> entities = Collections.synchronizedList(Lists.newArrayList()); // DivineMC - Optimize collections
public boolean loaded; @Nullable
public final ServerLevel level; // CraftBukkit - type private CarvingMask carvingMask;
@Nullable @Nullable

View File

@@ -0,0 +1,221 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Thu, 24 Jul 2025 14:07:47 +0300
Subject: [PATCH] Optimize level ticking
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 386fdc23b35675a7db66d16bf2a8a6dd5b44059a..4934ce03ac533d9c60674632cdac6621e62f6b44 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -908,9 +908,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper start - optimise random ticking
private final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed());
+ // DivineMC start - Optimize level ticking
private void optimiseRandomTick(final LevelChunk chunk, final int tickSpeed) {
final LevelChunkSection[] sections = chunk.getSections();
- final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection((ServerLevel)(Object)this);
+ final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(this); // DivineMC - Optimize level ticking
final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = this.simpleRandom;
final boolean doubleTickFluids = !ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC224294();
@@ -919,42 +920,38 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
final int offsetZ = cpos.z << 4;
for (int sectionIndex = 0, sectionsLen = sections.length; sectionIndex < sectionsLen; sectionIndex++) {
- final int offsetY = (sectionIndex + minSection) << 4;
final LevelChunkSection section = sections[sectionIndex];
+ if (!section.isRandomlyTickingBlocks()) continue;
+ final int offsetY = (sectionIndex + minSection) << 4;
final net.minecraft.world.level.chunk.PalettedContainer<net.minecraft.world.level.block.state.BlockState> states = section.states;
- if (!section.isRandomlyTickingBlocks()) {
- continue;
- }
- final ca.spottedleaf.moonrise.common.list.ShortList tickList = ((ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection)section).moonrise$getTickingBlockList();
+ final ca.spottedleaf.moonrise.common.list.ShortList tickList = section.moonrise$getTickingBlockList();
for (int i = 0; i < tickSpeed; ++i) {
- final int tickingBlocks = tickList.size();
final int index = simpleRandom.nextInt() & ((16 * 16 * 16) - 1);
- if (index >= tickingBlocks) {
+ if (index >= tickList.size()) {
// most of the time we fall here
continue;
}
- final int location = (int)tickList.getRaw(index) & 0xFFFF;
+ final int location = tickList.getRaw(index);
final BlockState state = states.get(location);
// do not use a mutable pos, as some random tick implementations store the input without calling immutable()!
- final BlockPos pos = new BlockPos((location & 15) | offsetX, ((location >>> (4 + 4)) & 15) | offsetY, ((location >>> 4) & 15) | offsetZ);
+ final BlockPos pos = new BlockPos((location & 15) | offsetX, (location >>> (4 + 4)) | offsetY, ((location >>> 4) & 15) | offsetZ);
- state.randomTick((ServerLevel)(Object)this, pos, simpleRandom);
+ state.randomTick(this, pos, simpleRandom);
if (doubleTickFluids) {
final FluidState fluidState = state.getFluidState();
if (fluidState.isRandomlyTicking()) {
- fluidState.randomTick((ServerLevel)(Object)this, pos, simpleRandom);
+ fluidState.randomTick(this, pos, simpleRandom);
}
}
}
}
-
- return;
}
+ // DivineMC end - Optimize level ticking
// Paper end - optimise random ticking
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 24f13e2b0b694ff4dd01aeea876ef874f1828304..404ed7c6ebe2364b9404df6e29d07a0aed83ed08 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -75,7 +75,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
return "<null>";
}
};
- private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = Maps.newHashMap();
+ private final Map<BlockPos, LevelChunk.RebindableTickingBlockEntityWrapper> tickersInLevel = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // DivineMC - Optimize level ticking
public boolean loaded;
public final ServerLevel level; // CraftBukkit - type
@Nullable
diff --git a/net/minecraft/world/ticks/LevelChunkTicks.java b/net/minecraft/world/ticks/LevelChunkTicks.java
index 66d0a6390febe929ef774b0a7813329015bc8cc2..c17549c4f8a877852c4b86453b1db7b17aab4665 100644
--- a/net/minecraft/world/ticks/LevelChunkTicks.java
+++ b/net/minecraft/world/ticks/LevelChunkTicks.java
@@ -14,10 +14,10 @@ import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickContainerAccess<T>, ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks { // Paper - rewrite chunk system
- private final Queue<ScheduledTick<T>> tickQueue = new PriorityQueue<>(ScheduledTick.DRAIN_ORDER);
+ private final Queue<ScheduledTick<T>> tickQueue = new java.util.concurrent.PriorityBlockingQueue<>(11, ScheduledTick.DRAIN_ORDER); // DivineMC - Optimize level ticking
@Nullable
private List<SavedTick<T>> pendingTicks;
- private final Set<ScheduledTick<?>> ticksPerPosition = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH);
+ private final Set<ScheduledTick<?>> ticksPerPosition = it.unimi.dsi.fastutil.objects.ObjectSets.synchronize(new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH)); // DivineMC - Optimize level ticking
@Nullable
private BiConsumer<LevelChunkTicks<T>, ScheduledTick<T>> onTickAdded;
@@ -67,10 +67,18 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
@Nullable
public ScheduledTick<T> poll() {
- ScheduledTick<T> scheduledTick = this.tickQueue.poll();
- if (scheduledTick != null) {
- this.ticksPerPosition.remove(scheduledTick); this.dirty = true; // Paper - rewrite chunk system
+ // DivineMC start - Optimize collections
+ ScheduledTick<T> scheduledTick = null;
+ try {
+ scheduledTick = this.tickQueue.poll();
+ if (scheduledTick != null) {
+ this.ticksPerPosition.remove(scheduledTick); this.dirty = true; // Paper - rewrite chunk system
+ }
+ } catch (Exception e) {
+ net.minecraft.server.MinecraftServer.LOGGER.error("Encountered caught exception when polling chunk ticks, blocking and returning null.", e);
+ return null;
}
+ // DivineMC end - Optimize collections
return scheduledTick;
}
@@ -83,6 +91,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
}
private void scheduleUnchecked(ScheduledTick<T> tick) {
+ if (tick == null) return; // DivineMC - Optimize level ticking
this.tickQueue.add(tick);
if (this.onTickAdded != null) {
this.onTickAdded.accept(this, tick);
@@ -124,6 +133,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
}
for (ScheduledTick<T> scheduledTick : this.tickQueue) {
+ if (scheduledTick == null) continue; // DivineMC - Optimize level ticking
list.add(scheduledTick.toSavedTick(gametime));
}
diff --git a/net/minecraft/world/ticks/LevelTicks.java b/net/minecraft/world/ticks/LevelTicks.java
index c7f9485191dc797de78e6524c5c2c737581ed838..14f2d0088cd9e6d4a2eb084439bab18bd365c41f 100644
--- a/net/minecraft/world/ticks/LevelTicks.java
+++ b/net/minecraft/world/ticks/LevelTicks.java
@@ -30,17 +30,20 @@ public class LevelTicks<T> implements LevelTickAccess<T> {
private static final Comparator<LevelChunkTicks<?>> CONTAINER_DRAIN_ORDER = (levelChunkTicks, levelChunkTicks1) -> ScheduledTick.INTRA_TICK_DRAIN_ORDER
.compare(levelChunkTicks.peek(), levelChunkTicks1.peek());
private final LongPredicate tickCheck;
- private final Long2ObjectMap<LevelChunkTicks<T>> allContainers = new Long2ObjectOpenHashMap<>();
- private final Long2LongMap nextTickForContainer = Util.make(new Long2LongOpenHashMap(), map -> map.defaultReturnValue(Long.MAX_VALUE));
- private final Queue<LevelChunkTicks<T>> containersToTick = new PriorityQueue<>(CONTAINER_DRAIN_ORDER);
- private final Queue<ScheduledTick<T>> toRunThisTick = new ArrayDeque<>();
+ // DivineMC start - Optimize collections
+ private final Long2ObjectMap<LevelChunkTicks<T>> allContainers = it.unimi.dsi.fastutil.longs.Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
+ private final java.util.Map<Long, Long> nextTickForContainer = new java.util.concurrent.ConcurrentHashMap<>();
+ private final Queue<LevelChunkTicks<T>> containersToTick = new java.util.concurrent.PriorityBlockingQueue<>(11, CONTAINER_DRAIN_ORDER);
+ private final Queue<ScheduledTick<T>> toRunThisTick = new java.util.concurrent.ConcurrentLinkedQueue<>();
+ // DivineMC end - Optimize collections
private final List<ScheduledTick<T>> alreadyRunThisTick = new ArrayList<>();
- private final Set<ScheduledTick<?>> toRunThisTickSet = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH);
+ private final Set<ScheduledTick<?>> toRunThisTickSet = com.google.common.collect.Sets.newConcurrentHashSet(); // DivineMC - Optimize level ticking
private final BiConsumer<LevelChunkTicks<T>, ScheduledTick<T>> chunkScheduleUpdater = (levelChunkTicks, scheduledTick) -> {
if (scheduledTick.equals(levelChunkTicks.peek())) {
this.updateContainerScheduling(scheduledTick);
}
};
+ private final java.util.concurrent.atomic.AtomicInteger toRunThisTickCount = new java.util.concurrent.atomic.AtomicInteger(0); // DivineMC - Optimize level ticking
public LevelTicks(LongPredicate tickCheck) {
this.tickCheck = tickCheck;
@@ -90,12 +93,14 @@ public class LevelTicks<T> implements LevelTickAccess<T> {
}
private void sortContainersToTick(long gameTime) {
- ObjectIterator<Entry> objectIterator = Long2LongMaps.fastIterator(this.nextTickForContainer);
+ java.util.Iterator<java.util.Map.Entry<Long, Long>> objectIterator = this.nextTickForContainer.entrySet().iterator(); // DivineMC - Optimize level ticking
while (objectIterator.hasNext()) {
- Entry entry = objectIterator.next();
- long longKey = entry.getLongKey();
- long longValue = entry.getLongValue();
+ // DivineMC start - Optimize collections
+ java.util.Map.Entry<Long, Long> entry = objectIterator.next();
+ long longKey = entry.getKey();
+ long longValue = entry.getValue();
+ // DivineMC end - Optimize collections
if (longValue <= gameTime) {
LevelChunkTicks<T> levelChunkTicks = this.allContainers.get(longKey);
if (levelChunkTicks == null) {
@@ -162,16 +167,19 @@ public class LevelTicks<T> implements LevelTickAccess<T> {
}
private void scheduleForThisTick(ScheduledTick<T> tick) {
+ if (tick == null) return; // DivineMC - Optimize level ticking
this.toRunThisTick.add(tick);
+ this.toRunThisTickCount.incrementAndGet(); // DivineMC - Optimize level ticking
}
private boolean canScheduleMoreTicks(int maxAllowedTicks) {
- return this.toRunThisTick.size() < maxAllowedTicks;
+ return this.toRunThisTickCount.get() < maxAllowedTicks; // DivineMC - Optimize level ticking
}
private void runCollectedTicks(BiConsumer<BlockPos, T> ticker) {
while (!this.toRunThisTick.isEmpty()) {
ScheduledTick<T> scheduledTick = this.toRunThisTick.poll();
+ this.toRunThisTickCount.decrementAndGet(); // DivineMC - Optimize level ticking
if (!this.toRunThisTickSet.isEmpty()) {
this.toRunThisTickSet.remove(scheduledTick);
}
@@ -182,7 +190,7 @@ public class LevelTicks<T> implements LevelTickAccess<T> {
}
private void cleanupAfterTick() {
- this.toRunThisTick.clear();
+ this.toRunThisTickCount.set(0); // DivineMC - Optimize level ticking
this.containersToTick.clear();
this.alreadyRunThisTick.clear();
this.toRunThisTickSet.clear();

View File

@@ -0,0 +1,480 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Mon, 11 Aug 2025 02:42:19 +0300
Subject: [PATCH] Optimize Moonrise
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 93272808d94e81d31af728ebe85df9a2bc7aedab..b47be4b838f4c7f6c3fb62e4e18105c6b4972016 100644
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
@@ -59,7 +59,7 @@ 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<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
+ private final it.unimi.dsi.fastutil.objects.Reference2ReferenceMap<ServerPlayer, TrackedPlayer[]> players = it.unimi.dsi.fastutil.objects.Reference2ReferenceMaps.synchronize(new Reference2ReferenceOpenHashMap<>()); // DivineMC - Optimize collections
// DivineMC start - Multithreaded Tracker
private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap<TrackedChunk> byChunk;
{
@@ -70,10 +70,10 @@ public final class NearbyPlayers {
}
}
// DivineMC end - Multithreaded Tracker
- private final Long2ReferenceOpenHashMap<ReferenceList<ServerPlayer>>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES];
+ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap<ReferenceList<ServerPlayer>>[] directByChunk = new it.unimi.dsi.fastutil.longs.Long2ReferenceMap[TOTAL_MAP_TYPES]; // DivineMC - Optimize collections
{
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 - Optimize collections
}
}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
index 57fec1f9a210d2ecb74ff7b05cec790ae77f9178..4d0e904d7d7659b24a883893cef167f3e80dfa36 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
@@ -73,37 +73,51 @@ public final class ChunkHolderManager {
private static final long NO_TIMEOUT_MARKER = Long.MIN_VALUE;
public final ReentrantAreaLock ticketLockArea;
- private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>();
- private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> sectionToChunkToExpireCount = new ConcurrentLong2ReferenceChainedHashTable<>();
+ // DivineMC start - Optimize Moonrise
+ private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket>> tickets = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(20, 0.9F);
+ private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> sectionToChunkToExpireCount = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(20, 0.9F);
+ // DivineMC end - Optimize Moonrise
final ChunkUnloadQueue unloadQueue;
- private final ConcurrentLong2ReferenceChainedHashTable<NewChunkHolder> chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(16384, 0.25f);
+ private final ConcurrentLong2ReferenceChainedHashTable<NewChunkHolder> chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(20, 0.9F); // DivineMC - Optimize Moonrise
private final ServerLevel world;
private final ChunkTaskScheduler taskScheduler;
private long currentTick;
- private final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = new ArrayDeque<>();
- private final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = new MultiThreadedQueue<>();
- private final ObjectRBTreeSet<NewChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> {
- if (c1 == c2) {
- return 0;
- }
+ // DivineMC start - Optimize Moonrise
+ public static class LevelHolderData {
+ private final java.util.concurrent.ConcurrentLinkedDeque<NewChunkHolder> pendingFullLoadUpdate = new java.util.concurrent.ConcurrentLinkedDeque<>();
+ private final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = new MultiThreadedQueue<>();
+ private final ObjectRBTreeSet<NewChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> {
+ if (c1 == c2) {
+ return 0;
+ }
- final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave);
+ final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave);
- if (saveTickCompare != 0) {
- return saveTickCompare;
- }
+ if (saveTickCompare != 0) {
+ return saveTickCompare;
+ }
+
+ final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ);
+ final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ);
- final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ);
- final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ);
+ if (coord1 == coord2) {
+ throw new IllegalStateException("Duplicate chunkholder in auto save queue");
+ }
+
+ return Long.compare(coord1, coord2);
+ });
+ }
- if (coord1 == coord2) {
- throw new IllegalStateException("Duplicate chunkholder in auto save queue");
+ public LevelHolderData getData() {
+ if (this.world == null) {
+ throw new RuntimeException("World was null!");
}
- return Long.compare(coord1, coord2);
- });
+ return world.chunkHolderData;
+ }
+ // DivineMC end - Optimize Moonrise
private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> ticketCounters = new ConcurrentLong2ReferenceChainedHashTable<>();
@@ -226,26 +240,29 @@ public final class ChunkHolderManager {
this.taskScheduler.setShutdown(true);
}
- void ensureInAutosave(final NewChunkHolder holder) {
- if (!this.autoSaveQueue.contains(holder)) {
+ // DivineMC start - Optimize Moonrise
+ synchronized void ensureInAutosave(final NewChunkHolder holder) {
+ final LevelHolderData data = getData();
+ if (!data.autoSaveQueue.contains(holder)) {
holder.lastAutoSave = this.currentTick;
- this.autoSaveQueue.add(holder);
+ data.autoSaveQueue.add(holder);
}
}
- public void autoSave() {
+ public synchronized void autoSave() {
+ final LevelHolderData data = getData();
final List<NewChunkHolder> reschedule = new ArrayList<>();
final long currentTick = this.currentTick;
final long maxSaveTime = currentTick - Math.max(1L, PlatformHooks.get().configAutoSaveInterval(this.world));
final int maxToSave = PlatformHooks.get().configMaxAutoSavePerTick(this.world);
- for (int autoSaved = 0; autoSaved < maxToSave && !this.autoSaveQueue.isEmpty();) {
- final NewChunkHolder holder = this.autoSaveQueue.first();
+ for (int autoSaved = 0; autoSaved < maxToSave && !data.autoSaveQueue.isEmpty();) {
+ final NewChunkHolder holder = data.autoSaveQueue.first();
if (holder.lastAutoSave > maxSaveTime) {
break;
}
- this.autoSaveQueue.remove(holder);
+ data.autoSaveQueue.remove(holder);
holder.lastAutoSave = currentTick;
if (holder.save(false) != null) {
@@ -259,10 +276,11 @@ public final class ChunkHolderManager {
for (final NewChunkHolder holder : reschedule) {
if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) {
- this.autoSaveQueue.add(holder);
+ data.autoSaveQueue.add(holder);
}
}
}
+ // DivineMC end - Optimize Moonrise
public void saveAllChunks(final boolean flush, final boolean shutdown, final boolean logProgress) {
final List<NewChunkHolder> holders = this.getChunkHolders();
@@ -461,8 +479,8 @@ public final class ChunkHolderManager {
final Long2ObjectOpenHashMap<SortedArraySet<Ticket>> ret = new Long2ObjectOpenHashMap<>();
final Long2ObjectOpenHashMap<LongArrayList> sections = new Long2ObjectOpenHashMap<>();
final int sectionShift = this.taskScheduler.getChunkSystemLockShift();
- for (final PrimitiveIterator.OfLong iterator = this.tickets.keyIterator(); iterator.hasNext();) {
- final long coord = iterator.nextLong();
+ for (final Iterator<Long> iterator = this.tickets.keyIterator(); iterator.hasNext();) { // DivineMC - Optimize Moonrise
+ final long coord = iterator.next(); // DivineMC - Optimize Moonrise
sections.computeIfAbsent(
CoordinateUtils.getChunkKey(
CoordinateUtils.getChunkX(coord) >> sectionShift,
@@ -559,7 +577,7 @@ public final class ChunkHolderManager {
chunkZ >> sectionShift
);
- this.sectionToChunkToExpireCount.computeIfAbsent(sectionKey, (final long keyInMap) -> {
+ this.sectionToChunkToExpireCount.computeIfAbsent(sectionKey, (keyInMap) -> { // DivineMC - Optimize Moonrise
return new Long2IntOpenHashMap();
}).addTo(chunkKey, 1);
}
@@ -603,8 +621,8 @@ public final class ChunkHolderManager {
final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null;
try {
- final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> {
- return (SortedArraySet)SortedArraySet.create(4);
+ final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (keyInMap) -> { // DivineMC - Optimize Moonrise
+ return SortedArraySet.create(4); // DivineMC - Optimize Moonrise
});
final int levelBefore = getTicketLevelAt(ticketsAtChunk);
@@ -784,8 +802,8 @@ public final class ChunkHolderManager {
final Long2ObjectOpenHashMap<LongArrayList> sections = new Long2ObjectOpenHashMap<>();
final int sectionShift = this.taskScheduler.getChunkSystemLockShift();
- for (final PrimitiveIterator.OfLong iterator = this.tickets.keyIterator(); iterator.hasNext();) {
- final long coord = iterator.nextLong();
+ for (final Iterator<Long> iterator = this.tickets.keyIterator(); iterator.hasNext();) { // DivineMC - Optimize Moonrise
+ final long coord = iterator.next(); // DivineMC - Optimize Moonrise
sections.computeIfAbsent(
CoordinateUtils.getChunkKey(
CoordinateUtils.getChunkX(coord) >> sectionShift,
@@ -836,8 +854,8 @@ public final class ChunkHolderManager {
final List<ChunkProgressionTask> scheduledTasks = new ArrayList<>();
final List<NewChunkHolder> changedFullStatus = new ArrayList<>();
- for (final PrimitiveIterator.OfLong iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) {
- final long sectionKey = iterator.nextLong();
+ for (final Iterator<Long> iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) { // DivineMC - Optimize Moonrise
+ final long sectionKey = iterator.next(); // DivineMC - Optimize Moonrise
if (!this.sectionToChunkToExpireCount.containsKey(sectionKey)) {
// removed concurrently
@@ -1145,18 +1163,18 @@ public final class ChunkHolderManager {
if (org.bxteam.divinemc.config.DivineConfig.AsyncCategory.enableParallelWorldTicking && !TickThread.isTickThreadFor(world) || !TickThread.isTickThread()) { // DivineMC - Parallel world ticking
// These will be handled on the next ServerChunkCache$MainThreadExecutor#pollTask, as it runs the distance manager update
// which will invoke processTicketUpdates
- this.offThreadPendingFullLoadUpdate.addAll(changedFullStatus);
+ this.getData().offThreadPendingFullLoadUpdate.addAll(changedFullStatus); // DivineMC - Optimize Moonrise
} else {
- final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
+ final java.util.Deque<NewChunkHolder> pendingFullLoadUpdate = this.getData().pendingFullLoadUpdate; // DivineMC - Optimize Moonrise
for (int i = 0, len = changedFullStatus.size(); i < len; ++i) {
pendingFullLoadUpdate.add(changedFullStatus.get(i));
}
}
}
- private void removeChunkHolder(final NewChunkHolder holder) {
+ private synchronized void removeChunkHolder(final NewChunkHolder holder) { // DivineMC - Optimize Moonrise
holder.onUnload();
- this.autoSaveQueue.remove(holder);
+ this.getData().autoSaveQueue.remove(holder); // DivineMC - Optimize Moonrise
PlatformHooks.get().onChunkHolderDelete(this.world, holder.vanillaChunkHolder);
this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
}
@@ -1320,6 +1338,27 @@ public final class ChunkHolderManager {
}
}
+ // DivineMC start - Optimize Moonrise
+ 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());
+ }
+
+ public void markNonBlockTickingIfPossible(@org.jetbrains.annotations.NotNull NewChunkHolder newChunkHolder) {
+ this.blockTickingChunkHolders.remove(newChunkHolder.getCachedLongPos());
+ }
+
+ public void markEntityTicking(@org.jetbrains.annotations.NotNull NewChunkHolder newChunkHolder) {
+ this.entityTickingChunkHolders.add(newChunkHolder.getCachedLongPos());
+ }
+
+ public void markNonEntityTickingIfPossible(@org.jetbrains.annotations.NotNull NewChunkHolder newChunkHolder) {
+ this.entityTickingChunkHolders.remove(newChunkHolder.getCachedLongPos());
+ }
+ // DivineMC end - Optimize Moonrise
+
public enum TicketOperationType {
ADD, REMOVE, ADD_IF_REMOVED, ADD_AND_REMOVE
}
@@ -1479,8 +1518,10 @@ public final class ChunkHolderManager {
// only call on tick thread
private void processOffThreadFullUpdates() {
- final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
- final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = this.offThreadPendingFullLoadUpdate;
+ // DivineMC start - Optimize Moonrise
+ final java.util.concurrent.ConcurrentLinkedDeque<NewChunkHolder> pendingFullLoadUpdate = this.getData().pendingFullLoadUpdate;
+ final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = this.getData().offThreadPendingFullLoadUpdate;
+ // DivineMC end - Optimize Moonrise
NewChunkHolder toUpdate;
while ((toUpdate = offThreadPendingFullLoadUpdate.poll()) != null) {
@@ -1492,7 +1533,7 @@ public final class ChunkHolderManager {
private boolean processPendingFullUpdate() {
this.processOffThreadFullUpdates();
- final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
+ final java.util.Deque<NewChunkHolder> pendingFullLoadUpdate = this.getData().pendingFullLoadUpdate; // DivineMC - Optimize Moonrise
boolean ret = false;
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
index 2cc0e7c72d2b2e562452138f2b41fd1dcaf0570a..affa0dac8633ce3a43c9609888ed96d0aabdab5e 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
@@ -646,12 +646,20 @@ public final class NewChunkHolder {
}
public final ChunkHolder vanillaChunkHolder;
+ // DivineMC start - Optimize Moonrise
+ private final long cachedLongPos;
+
+ public long getCachedLongPos() {
+ return cachedLongPos;
+ }
+ // DivineMC end - Optimize Moonrise
public NewChunkHolder(final ServerLevel world, final int chunkX, final int chunkZ, final ChunkTaskScheduler scheduler) {
this.world = world;
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.scheduler = scheduler;
+ this.cachedLongPos = ((long)chunkZ << 32) | (chunkX & 0xFFFFFFFFL); // DivineMC - Optimize Moonrise
this.vanillaChunkHolder = new ChunkHolder(
new ChunkPos(chunkX, chunkZ), ChunkHolderManager.MAX_TICKET_LEVEL, world,
world.getLightEngine(), null, world.getChunkSource().chunkMap
@@ -792,9 +800,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 - Optimize Moonrise
+ private volatile UnloadTask chunkDataUnload;
+ private volatile UnloadTask entityDataUnload;
+ private volatile UnloadTask poiDataUnload;
+ // DivineMC end - Optimize Moonrise
public static final record UnloadTask(CallbackCompletable<CompoundTag> completable, PrioritisedExecutor.PrioritisedTask task,
LazyRunnable toRun) {}
@@ -879,7 +889,11 @@ public final class NewChunkHolder {
MoonriseRegionFileIO.scheduleSave(this.world, this.chunkX, this.chunkZ, data, type);
}
- this.getUnloadTask(type).completable().complete(data);
+ // DivineMC start - Optimize Moonrise
+ UnloadTask task = this.getUnloadTask(type);
+ if (task == null) return;
+ task.completable().complete(data);
+ // DivineMC end - Optimize Moonrise
final ReentrantAreaLock.Node schedulingLock = this.scheduler.schedulingLockArea.lock(this.chunkX, this.chunkZ);
try {
// can only write to these fields while holding the schedule lock
@@ -1192,6 +1206,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 - Optimize Moonrise
if (loaded) {
if (holder.setNeighbourFullLoaded(-dx, -dz)) {
changedFullStatus.add(holder);
@@ -1216,6 +1231,19 @@ public final class NewChunkHolder {
private void updateCurrentState(final FullChunkStatus to) {
this.currentFullChunkStatus = to;
+ // DivineMC start - Optimize Moonrise
+ if (to.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markBlockTicking(this);
+ } else {
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markNonBlockTickingIfPossible(this);
+ }
+
+ if (to.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markEntityTicking(this);
+ } else {
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markNonEntityTickingIfPossible(this);
+ }
+ // DivineMC end - Optimize Moonrise
}
// only to be called on the main thread, no locks need to be held
@@ -1350,7 +1378,7 @@ public final class NewChunkHolder {
return this.requestedGenStatus;
}
- private final Reference2ObjectOpenHashMap<ChunkStatus, List<Consumer<ChunkAccess>>> statusWaiters = new Reference2ObjectOpenHashMap<>();
+ private final Reference2ObjectMap<ChunkStatus, List<Consumer<ChunkAccess>>> statusWaiters = it.unimi.dsi.fastutil.objects.Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>()); // DivineMC - Optimize Moonrise
void addStatusConsumer(final ChunkStatus status, final Consumer<ChunkAccess> consumer) {
this.statusWaiters.computeIfAbsent(status, (final ChunkStatus keyInMap) -> {
@@ -1396,7 +1424,7 @@ public final class NewChunkHolder {
}, Priority.HIGHEST);
}
- private final Reference2ObjectOpenHashMap<FullChunkStatus, List<Consumer<LevelChunk>>> fullStatusWaiters = new Reference2ObjectOpenHashMap<>();
+ private final Reference2ObjectMap<FullChunkStatus, List<Consumer<LevelChunk>>> fullStatusWaiters = it.unimi.dsi.fastutil.objects.Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>()); // DivineMC - Optimize Moonrise
void addFullStatusConsumer(final FullChunkStatus status, final Consumer<LevelChunk> consumer) {
this.fullStatusWaiters.computeIfAbsent(status, (final FullChunkStatus keyInMap) -> {
diff --git a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..1ac37db68341672481cd4bbdf7bab90572c35453 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 - Optimize Moonrise
if (!this.isDirty()) {
return false;
}
diff --git a/net/minecraft/server/level/DistanceManager.java b/net/minecraft/server/level/DistanceManager.java
index 50bc5b940812432bc472e5b272582efb8bbfc7a7..0bece4ed69b332174cbe37f82df1f7da9276d591 100644
--- a/net/minecraft/server/level/DistanceManager.java
+++ b/net/minecraft/server/level/DistanceManager.java
@@ -127,15 +127,13 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches
public boolean inEntityTickingRange(long chunkPos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(chunkPos);
- return chunkHolder != null && chunkHolder.isEntityTickingReady();
+ return this.moonrise$getChunkHolderManager().entityTickingChunkHolders.contains(chunkPos); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}
public boolean inBlockTickingRange(long chunkPos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(chunkPos);
- return chunkHolder != null && chunkHolder.isTickingReady();
+ return this.moonrise$getChunkHolderManager().blockTickingChunkHolders.contains(chunkPos); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 440bd8f16664fdc29db69b92f2c856dd7cc4ffd1..0abfd610caf529952fee857d881920a5ddad8ed3 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -667,8 +667,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
public boolean isPositionTicking(long chunkPos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder newChunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos);
- return newChunkHolder != null && newChunkHolder.isTickingReady();
+ return ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.contains(chunkPos); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 4934ce03ac533d9c60674632cdac6621e62f6b44..b50afea7c2e4c61a3df196e74afd8f82b30aca8a 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -179,6 +179,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final ServerChunkCache chunkSource;
private final MinecraftServer server;
public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type
+ public final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.LevelHolderData chunkHolderData; // DivineMC - Optimize Moonrise
private int lastSpawnChunkRadius;
final EntityTickList entityTickList = new EntityTickList(this); // DivineMC - Parallel world ticking
private final ServerWaypointManager waypointManager;
@@ -691,6 +692,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper start - rewrite chunk system
this.moonrise$setEntityLookup(new ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup((ServerLevel)(Object)this, ((ServerLevel)(Object)this).new EntityCallbacks()));
this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this);
+ this.chunkHolderData = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.LevelHolderData(); // DivineMC - Optimize Moonrise
this.entityDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.EntityDataController(
new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.EntityDataController.EntityRegionFileStorage(
new RegionStorageInfo(levelStorageAccess.getLevelId(), dimension, "entities"),
@@ -846,8 +848,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public boolean shouldTickBlocksAt(long chunkPos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder holder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos);
- return holder != null && holder.isTickingReady();
+ return this.moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.contains(chunkPos); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}
@@ -2584,16 +2585,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public boolean isPositionTickingWithEntitiesLoaded(long chunkPos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos);
- // isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded
- return chunkHolder != null && chunkHolder.isTickingReady();
+ return this.moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.contains(chunkPos); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}
public boolean isPositionEntityTicking(BlockPos pos) {
// Paper start - rewrite chunk system
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(pos));
- return chunkHolder != null && chunkHolder.isEntityTickingReady();
+ return this.moonrise$getChunkTaskScheduler().chunkHolderManager.entityTickingChunkHolders.contains(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(pos)); // DivineMC - Optimize Moonrise
// Paper end - rewrite chunk system
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/ticks/LevelTicks.java
+++ b/net/minecraft/world/ticks/LevelTicks.java
@@ -191,7 +_,6 @@
}
private void cleanupAfterTick() {
- this.toRunThisTick.clear();
this.containersToTick.clear();
this.alreadyRunThisTick.clear();
this.toRunThisTickSet.clear();

View File

@@ -1,167 +0,0 @@
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<E> implements Iterable<E> {
-
- private static final Object[] EMPTY_LIST = new Object[0];
-
- private final Reference2IntOpenHashMap<E> 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<E> referenceToIndex) {
- this.references = references;
- this.count = count;
- this.referenceToIndex = referenceToIndex;
- }
-
- public ReferenceList<E> 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<E> extends ReferenceLists.SynchronizedList<E> {
+ 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<E>) 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<A> extends ReferenceArrayList<A> {
+ 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<E> 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

View File

@@ -0,0 +1,508 @@
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] Optimize Moonrise
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java
index 7fed43a1e7bcf35c4d7fd3224837a47fedd59860..6c002ba690a8cc7335276e039f49c4251076cc92 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java
@@ -1,5 +1,7 @@
package ca.spottedleaf.moonrise.common.list;
+import it.unimi.dsi.fastutil.ints.Int2IntMap;
+import it.unimi.dsi.fastutil.ints.Int2IntMaps;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.world.entity.Entity;
import java.util.Arrays;
@@ -13,7 +15,7 @@ import java.util.NoSuchElementException;
*/
public final class EntityList implements Iterable<Entity> {
- private final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f);
+ private final Int2IntMap entityToIndex = Int2IntMaps.synchronize(new Int2IntOpenHashMap(2, 0.8f)); // DivineMC - Optimize Moonrise
{
this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE);
}
@@ -27,11 +29,11 @@ public final class EntityList implements Iterable<Entity> {
return this.count;
}
- public boolean contains(final Entity entity) {
+ public synchronized boolean contains(final Entity entity) { // DivineMC - Optimize Moonrise
return this.entityToIndex.containsKey(entity.getId());
}
- public boolean remove(final Entity entity) {
+ public synchronized boolean remove(final Entity entity) { // DivineMC - Optimize Moonrise
final int index = this.entityToIndex.remove(entity.getId());
if (index == Integer.MIN_VALUE) {
return false;
@@ -50,7 +52,7 @@ public final class EntityList implements Iterable<Entity> {
return true;
}
- public boolean add(final Entity entity) {
+ public synchronized boolean add(final Entity entity) { // DivineMC - Optimize Moonrise
final int count = this.count;
final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count);
@@ -82,18 +84,18 @@ public final class EntityList implements Iterable<Entity> {
return this.entities[index];
}
- public Entity[] getRawData() {
+ public synchronized Entity[] getRawData() { // DivineMC - Optimize Moonrise
return this.entities;
}
- public void clear() {
+ public synchronized void clear() { // DivineMC - Optimize Moonrise
this.entityToIndex.clear();
Arrays.fill(this.entities, 0, this.count, null);
this.count = 0;
}
@Override
- public Iterator<Entity> iterator() {
+ public synchronized Iterator<Entity> iterator() { // DivineMC - Optimize Moonrise
return new Iterator<>() {
private Entity lastRet;
private int current;
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..c93a9d2de61c9aa789c0758de0bdafaa4af2c93f 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 - Optimize Moonrise
+import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
+import it.unimi.dsi.fastutil.objects.ReferenceLists;
-public final class ReferenceList<E> implements Iterable<E> {
-
- private static final Object[] EMPTY_LIST = new Object[0];
-
- private final Reference2IntOpenHashMap<E> 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<E> referenceToIndex) {
- this.references = references;
- this.count = count;
- this.referenceToIndex = referenceToIndex;
- }
-
- public ReferenceList<E> 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<E> extends ReferenceLists.SynchronizedList<E> {
+ 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<E>) 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<A> extends ReferenceArrayList<A> {
+ 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<E> 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 - Optimize Moonrise
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java
index 2bae9949ef325d0001aa638150fbbdf968367e75..f946e625dcfec5c6ee9bf90bb79ac1c2f84ec048 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/ShortList.java
@@ -1,11 +1,13 @@
package ca.spottedleaf.moonrise.common.list;
+import it.unimi.dsi.fastutil.shorts.Short2ShortMap;
+import it.unimi.dsi.fastutil.shorts.Short2ShortMaps;
import it.unimi.dsi.fastutil.shorts.Short2ShortOpenHashMap;
import java.util.Arrays;
public final class ShortList {
- private final Short2ShortOpenHashMap map = new Short2ShortOpenHashMap();
+ private final Short2ShortMap map = Short2ShortMaps.synchronize(new Short2ShortOpenHashMap()); // DivineMC - Optimize Moonrise
{
this.map.defaultReturnValue(Short.MIN_VALUE);
}
@@ -13,13 +15,13 @@ public final class ShortList {
private static final short[] EMPTY_LIST = new short[0];
private short[] byIndex = EMPTY_LIST;
- private short count;
+ private volatile short count; // DivineMC - Optimize Moonrise
public int size() {
- return (int)this.count;
+ return this.count; // DivineMC - Optimize Moonrise
}
- public short getRaw(final int index) {
+ public synchronized short getRaw(final int index) { // DivineMC - Optimize Moonrise
return this.byIndex[index];
}
@@ -30,8 +32,8 @@ public final class ShortList {
}
}
- public boolean add(final short value) {
- final int count = (int)this.count;
+ public synchronized boolean add(final short value) { // DivineMC - Optimize Moonrise
+ final int count = this.count; // DivineMC - Optimize Moonrise
final short currIndex = this.map.putIfAbsent(value, (short)count);
if (currIndex != Short.MIN_VALUE) {
@@ -51,7 +53,7 @@ public final class ShortList {
return true;
}
- public boolean remove(final short value) {
+ public synchronized boolean remove(final short value) { // DivineMC - Optimize Moonrise
final short index = this.map.remove(value);
if (index == Short.MIN_VALUE) {
return false;
@@ -70,7 +72,7 @@ public final class ShortList {
return true;
}
- public void clear() {
+ public synchronized void clear() { // DivineMC - Optimize Moonrise
this.count = (short)0;
this.map.clear();
}
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed26WayDistancePropagator3D.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed26WayDistancePropagator3D.java
index 460e27ab0506c83a28934800ee74ee886d4b025e..59e80748de2b0b35ecf25739e1876ebcbce7eca5 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed26WayDistancePropagator3D.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed26WayDistancePropagator3D.java
@@ -15,7 +15,7 @@ public final class Delayed26WayDistancePropagator3D {
// Generally updates to positions are made close to other updates, so we link to decrease cache misses when
// propagating updates
- protected final LongLinkedOpenHashSet updatedSources = new LongLinkedOpenHashSet();
+ protected final it.unimi.dsi.fastutil.longs.LongSet updatedSources = it.unimi.dsi.fastutil.longs.LongSets.synchronize(new LongLinkedOpenHashSet()); // DivineMC - Optimize Moonrise
@FunctionalInterface
public static interface LevelChangeCallback {
@@ -94,29 +94,29 @@ public final class Delayed26WayDistancePropagator3D {
protected final void addToIncreaseWorkQueue(final long coordinate, final byte level) {
final Delayed8WayDistancePropagator2D.WorkQueue queue = this.levelIncreaseWorkQueues[level];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelIncreaseWorkQueueBitset |= (1L << level);
}
protected final void addToIncreaseWorkQueue(final long coordinate, final byte index, final byte level) {
final Delayed8WayDistancePropagator2D.WorkQueue queue = this.levelIncreaseWorkQueues[index];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelIncreaseWorkQueueBitset |= (1L << index);
}
protected final void addToRemoveWorkQueue(final long coordinate, final byte level) {
final Delayed8WayDistancePropagator2D.WorkQueue queue = this.levelRemoveWorkQueues[level];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelRemoveWorkQueueBitset |= (1L << level);
}
- public boolean propagateUpdates() {
+ public synchronized boolean propagateUpdates() { // DivineMC - Optimize Moonrise
if (this.updatedSources.isEmpty()) {
return false;
}
@@ -157,15 +157,15 @@ public final class Delayed26WayDistancePropagator3D {
return ret;
}
- protected void propagateIncreases() {
+ protected synchronized void propagateIncreases() { // DivineMC - Optimize Moonrise
for (int queueIndex = 63 ^ Long.numberOfLeadingZeros(this.levelIncreaseWorkQueueBitset);
this.levelIncreaseWorkQueueBitset != 0L;
this.levelIncreaseWorkQueueBitset ^= (1L << queueIndex), queueIndex = 63 ^ Long.numberOfLeadingZeros(this.levelIncreaseWorkQueueBitset)) {
final Delayed8WayDistancePropagator2D.WorkQueue queue = this.levelIncreaseWorkQueues[queueIndex];
while (!queue.queuedLevels.isEmpty()) {
- final long coordinate = queue.queuedCoordinates.removeFirstLong();
- byte level = queue.queuedLevels.removeFirstByte();
+ final long coordinate = queue.queuedCoordinates.removeFirst(); // DivineMC - Optimize Moonrise
+ byte level = queue.queuedLevels.removeFirst(); // DivineMC - Optimize Moonrise
final boolean neighbourCheck = level < 0;
@@ -226,15 +226,15 @@ public final class Delayed26WayDistancePropagator3D {
}
}
- protected void propagateDecreases() {
+ protected synchronized void propagateDecreases() { // DivineMC - Optimize Moonrise
for (int queueIndex = 63 ^ Long.numberOfLeadingZeros(this.levelRemoveWorkQueueBitset);
this.levelRemoveWorkQueueBitset != 0L;
this.levelRemoveWorkQueueBitset ^= (1L << queueIndex), queueIndex = 63 ^ Long.numberOfLeadingZeros(this.levelRemoveWorkQueueBitset)) {
final Delayed8WayDistancePropagator2D.WorkQueue queue = this.levelRemoveWorkQueues[queueIndex];
while (!queue.queuedLevels.isEmpty()) {
- final long coordinate = queue.queuedCoordinates.removeFirstLong();
- final byte level = queue.queuedLevels.removeFirstByte();
+ final long coordinate = queue.queuedCoordinates.removeFirst(); // DivineMC - Optimize Moonrise
+ final byte level = queue.queuedLevels.removeFirst(); // DivineMC - Optimize Moonrise
final byte currentLevel = this.levels.removeIfGreaterOrEqual(coordinate, level);
if (currentLevel == 0) {
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed8WayDistancePropagator2D.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed8WayDistancePropagator2D.java
index ab2fa1563d5e32a5313dfcc1da411cab45fb5ca0..f568fcf85667cd3fe53f59e08451096de5fa3492 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed8WayDistancePropagator2D.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/Delayed8WayDistancePropagator2D.java
@@ -356,24 +356,24 @@ public final class Delayed8WayDistancePropagator2D {
protected final void addToIncreaseWorkQueue(final long coordinate, final byte level) {
final WorkQueue queue = this.levelIncreaseWorkQueues[level];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelIncreaseWorkQueueBitset |= (1L << level);
}
protected final void addToIncreaseWorkQueue(final long coordinate, final byte index, final byte level) {
final WorkQueue queue = this.levelIncreaseWorkQueues[index];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelIncreaseWorkQueueBitset |= (1L << index);
}
protected final void addToRemoveWorkQueue(final long coordinate, final byte level) {
final WorkQueue queue = this.levelRemoveWorkQueues[level];
- queue.queuedCoordinates.enqueue(coordinate);
- queue.queuedLevels.enqueue(level);
+ queue.queuedCoordinates.add(coordinate); // DivineMC - Optimize Moonrise
+ queue.queuedLevels.add(level); // DivineMC - Optimize Moonrise
this.levelRemoveWorkQueueBitset |= (1L << level);
}
@@ -426,8 +426,8 @@ public final class Delayed8WayDistancePropagator2D {
final WorkQueue queue = this.levelIncreaseWorkQueues[queueIndex];
while (!queue.queuedLevels.isEmpty()) {
- final long coordinate = queue.queuedCoordinates.removeFirstLong();
- byte level = queue.queuedLevels.removeFirstByte();
+ final long coordinate = queue.queuedCoordinates.removeFirst(); // DivineMC - Optimize Moonrise
+ byte level = queue.queuedLevels.removeFirst(); // DivineMC - Optimize Moonrise
final boolean neighbourCheck = level < 0;
@@ -492,8 +492,8 @@ public final class Delayed8WayDistancePropagator2D {
final WorkQueue queue = this.levelRemoveWorkQueues[queueIndex];
while (!queue.queuedLevels.isEmpty()) {
- final long coordinate = queue.queuedCoordinates.removeFirstLong();
- final byte level = queue.queuedLevels.removeFirstByte();
+ final long coordinate = queue.queuedCoordinates.removeFirst(); // DivineMC - Optimize Moonrise
+ final byte level = queue.queuedLevels.removeFirst(); // DivineMC - Optimize Moonrise
final byte currentLevel = this.levels.removeIfGreaterOrEqual(coordinate, level);
if (currentLevel == 0) {
@@ -561,7 +561,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- private int find(final long k) {
+ private synchronized int find(final long k) { // DivineMC - Optimize Moonrise
if (k == 0L) {
return this.containsNullKey ? this.n : -(this.n + 1);
} else {
@@ -585,7 +585,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- private void insert(final int pos, final long k, final byte v) {
+ private synchronized void insert(final int pos, final long k, final byte v) { // DivineMC - Optimize Moonrise
if (pos == this.n) {
this.containsNullKey = true;
}
@@ -598,7 +598,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- public byte putIfGreater(final long key, final byte value) {
+ public synchronized byte putIfGreater(final long key, final byte value) { // DivineMC - Optimize Moonrise
final int pos = this.find(key);
if (pos < 0) {
if (this.defRetValue < value) {
@@ -616,7 +616,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- private void removeEntry(final int pos) {
+ private synchronized void removeEntry(final int pos) { // DivineMC - Optimize Moonrise
--this.size;
this.shiftKeys(pos);
if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) {
@@ -625,7 +625,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- private void removeNullEntry() {
+ private synchronized void removeNullEntry() { // DivineMC - Optimize Moonrise
this.containsNullKey = false;
--this.size;
if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) {
@@ -634,7 +634,7 @@ public final class Delayed8WayDistancePropagator2D {
}
// copied from superclass
- public byte removeIfGreaterOrEqual(final long key, final byte value) {
+ public synchronized byte removeIfGreaterOrEqual(final long key, final byte value) { // DivineMC - Optimize Moonrise
if (key == 0L) {
if (!this.containsNullKey) {
return this.defRetValue;
@@ -679,8 +679,8 @@ public final class Delayed8WayDistancePropagator2D {
protected static final class WorkQueue {
- public final NoResizeLongArrayFIFODeque queuedCoordinates = new NoResizeLongArrayFIFODeque();
- public final NoResizeByteArrayFIFODeque queuedLevels = new NoResizeByteArrayFIFODeque();
+ public final java.util.concurrent.ConcurrentLinkedDeque<Long> queuedCoordinates = new java.util.concurrent.ConcurrentLinkedDeque<>();
+ public final java.util.concurrent.ConcurrentLinkedDeque<Byte> queuedLevels = new java.util.concurrent.ConcurrentLinkedDeque<>();
}