@@ -124,7 +124,7 @@ index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f549
124
124
+ }
125
125
+ }
126
126
diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
127
- index 7ca275826609bcf96f103a8c50beaa47c3b4068b..045a83f944ebe3e5e969e4b414760413f8d634fc 100644
127
+ index 7ca275826609bcf96f103a8c50beaa47c3b4068b..dc5399bd5dba9dd33a7cfd644327c2568a6ad051 100644
128
128
--- a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
129
129
+++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
130
130
@@ -4,6 +4,7 @@ import com.destroystokyo.paper.util.maplist.ReferenceList;
@@ -135,64 +135,71 @@ index 7ca275826609bcf96f103a8c50beaa47c3b4068b..045a83f944ebe3e5e969e4b414760413
135
135
import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager;
136
136
import io.papermc.paper.util.CoordinateUtils;
137
137
import io.papermc.paper.util.TickThread;
138
- @@ -14,6 +15,8 @@ import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
138
+ @@ -14,6 +15,7 @@ import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
139
139
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
140
140
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
141
141
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
142
142
+ import me.earthme.luminol.LuminolConfig;
143
- + import me.earthme.luminol.utils.AsyncMobSpawnExecutor;
144
143
import net.minecraft.CrashReport;
145
144
import net.minecraft.ReportedException;
146
145
import net.minecraft.core.BlockPos;
147
- @@ -58,6 +61,7 @@ import java.util.HashMap;
146
+ @@ -58,6 +60,10 @@ import java.util.HashMap;
148
147
import java.util.Iterator;
149
148
import java.util.List;
150
149
import java.util.Map;
151
150
+ import java.util.concurrent.CompletableFuture;
151
+ + import java.util.concurrent.LinkedBlockingQueue;
152
+ + import java.util.concurrent.ThreadPoolExecutor;
153
+ + import java.util.concurrent.TimeUnit;
152
154
import java.util.function.Consumer;
153
155
import java.util.function.Predicate;
154
156
155
- @@ -145,6 +149,11 @@ public final class RegionizedWorldData {
157
+ @@ -145,6 +151,10 @@ public final class RegionizedWorldData {
156
158
into.wanderingTraderSpawnDelay = Math.max(from.wanderingTraderSpawnDelay, into.wanderingTraderSpawnDelay);
157
159
into.wanderingTraderSpawnChance = Math.max(from.wanderingTraderSpawnChance, into.wanderingTraderSpawnChance);
158
160
}
159
161
+
160
162
+ //Luminol start - Async mob spawning
161
- + from.asyncMobSpawnExecutor.forceTerminate(); //Just terminate and do nothing
162
163
+ from.lastAsyncSpawnStateTask = null; //Discard the task currently processing
163
164
+ //Luminol end
164
165
}
165
166
166
167
@Override
167
- @@ -302,6 +311,15 @@ public final class RegionizedWorldData {
168
+ @@ -302,6 +312,10 @@ public final class RegionizedWorldData {
168
169
regionizedWorldData.wanderingTraderSpawnDelay = from.wanderingTraderSpawnDelay;
169
170
regionizedWorldData.villageSiegeState = new VillageSiegeState(); // just re set it, as the spawn pos will be invalid
170
171
}
171
172
+
172
173
+ //Luminol start - Async mob spawning
173
174
+ from.lastAsyncSpawnStateTask = null; //Reset the task
174
- + from.asyncMobSpawnExecutor.dropAllTasks(); //Reset tasks
175
- +
176
- + if (!from.asyncMobSpawnExecutor.isRunning() && LuminolConfig.enableAsyncMobSpawning){
177
- + from.asyncMobSpawnExecutor.startExecutor();
178
- + }
179
175
+ //Luminol end
180
176
}
181
177
};
182
178
183
- @@ -398,6 +416,11 @@ public final class RegionizedWorldData {
179
+ @@ -398,6 +412,22 @@ public final class RegionizedWorldData {
184
180
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos;
185
181
public final Long2IntOpenHashMap chunksBeingWorkedOn = new Long2IntOpenHashMap();
186
182
187
183
+ //Luminol start - Asnc mob spawning
188
- + public final AsyncMobSpawnExecutor asyncMobSpawnExecutor = new AsyncMobSpawnExecutor();
189
184
+ public volatile CompletableFuture<NaturalSpawner.SpawnState> lastAsyncSpawnStateTask = null;
185
+ + public static ThreadPoolExecutor ASYNC_MOB_SPAWNING_EXECUTOR;
186
+ + public static void initMobSpawningExecutor(){
187
+ + if (LuminolConfig.enableAsyncMobSpawning){
188
+ + ASYNC_MOB_SPAWNING_EXECUTOR = new ThreadPoolExecutor(
189
+ + 1,
190
+ + Integer.MAX_VALUE,
191
+ + 1,
192
+ + TimeUnit.MINUTES,
193
+ + new LinkedBlockingQueue<>()
194
+ + );
195
+ + }
196
+ + }
190
197
+ //Luminol end
191
198
+
192
199
public static final class TempCollisionList<T> {
193
200
final UnsafeList<T> list = new UnsafeList<>(64);
194
201
boolean inUse;
195
- @@ -430,7 +453 ,7 @@ public final class RegionizedWorldData {
202
+ @@ -430,7 +460 ,7 @@ public final class RegionizedWorldData {
196
203
197
204
// Mob spawning
198
205
private final PooledLinkedHashSets<ServerPlayer> pooledHashSets = new PooledLinkedHashSets<>();
@@ -202,22 +209,31 @@ index 7ca275826609bcf96f103a8c50beaa47c3b4068b..045a83f944ebe3e5e969e4b414760413
202
209
public int patrolSpawnerNextTick = 0;
203
210
public int phantomSpawnerNextTick = 0;
204
211
diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java
205
- index e8cd180bab5c196db09ded74aea676b4412fc6e9..22ee6f520958fbc4301d82872faa4a8af4339a8e 100644
212
+ index e8cd180bab5c196db09ded74aea676b4412fc6e9..534f54be1495b1a8f754bec0eb1aba8306c1d902 100644
206
213
--- a/src/main/java/me/earthme/luminol/LuminolConfig.java
207
214
+++ b/src/main/java/me/earthme/luminol/LuminolConfig.java
208
- @@ -62,6 +62,7 @@ public class LuminolConfig {
215
+ @@ -2,6 +2,7 @@ package me.earthme.luminol;
216
+
217
+ import dev.kaiijumc.kaiiju.region.RegionFileFormat;
218
+ import com.electronwill.nightconfig.core.file.CommentedFileConfig;
219
+ + import io.papermc.paper.threadedregions.RegionizedWorldData;
220
+ import me.earthme.luminol.commands.TpsBarCommand;
221
+ import me.earthme.luminol.functions.GlobalServerTpsBar;
222
+ import net.minecraft.core.registries.BuiltInRegistries;
223
+ @@ -62,6 +63,7 @@ public class LuminolConfig {
209
224
public static boolean asyncPathProcessing = false;
210
225
public static int asyncPathProcessingMaxThreads = 0;
211
226
public static int asyncPathProcessingKeepalive = 60;
212
227
+ public static boolean enableAsyncMobSpawning = false;
213
228
214
229
public static void init() throws IOException {
215
230
PARENT_FOLDER.mkdir();
216
- @@ -188,6 +189,7 @@ public class LuminolConfig {
231
+ @@ -188,6 +190,8 @@ public class LuminolConfig {
217
232
asyncPathProcessingMaxThreads = Math.max(Runtime.getRuntime().availableProcessors() / 4, 1);
218
233
if (!asyncPathProcessing)
219
234
asyncPathProcessingMaxThreads = 0;
220
235
+ enableAsyncMobSpawning = get("optimizations.enable_async_mob_spawning",enableAsyncMobSpawning);
236
+ + RegionizedWorldData.initMobSpawningExecutor();
221
237
}
222
238
223
239
public static <T> T get(String key,T def){
@@ -299,10 +315,10 @@ index 0000000000000000000000000000000000000000..88d5b188ccfb17fe1ae4b08f32565f27
299
315
+ }
300
316
+ }
301
317
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
302
- index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..a50e6249eec7a8211b4674f34acd5d7104d825dd 100644
318
+ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..c470eafef884075b6e4d170adc2ced96a4beb517 100644
303
319
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
304
320
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
305
- @@ -11,13 +11,14 @@ import java.util.Collections;
321
+ @@ -11,13 +11,15 @@ import java.util.Collections;
306
322
import java.util.Iterator;
307
323
import java.util.List;
308
324
import java.util.Objects;
@@ -314,11 +330,12 @@ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..a50e6249eec7a8211b4674f34acd5d71
314
330
import java.util.function.Supplier;
315
331
import javax.annotation.Nullable;
316
332
+
333
+ + import io.papermc.paper.threadedregions.RegionizedWorldData;
317
334
+ import me.earthme.luminol.LuminolConfig;
318
335
import net.minecraft.Util;
319
336
import net.minecraft.core.BlockPos;
320
337
import net.minecraft.core.SectionPos;
321
- @@ -487,32 +488 ,38 @@ public class ServerChunkCache extends ChunkSource {
338
+ @@ -487,32 +489 ,38 @@ public class ServerChunkCache extends ChunkSource {
322
339
this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
323
340
int l = this.distanceManager.getNaturalSpawnChunkCount();
324
341
// Paper start - per player mob spawning
@@ -374,7 +391,7 @@ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..a50e6249eec7a8211b4674f34acd5d71
374
391
gameprofilerfiller.popPush("filteringLoadedChunks");
375
392
// Paper - optimise chunk tick iteration
376
393
// Paper - optimise chunk tick iteration
377
- @@ -610,7 +617 ,12 @@ public class ServerChunkCache extends ChunkSource {
394
+ @@ -610,7 +618 ,12 @@ public class ServerChunkCache extends ChunkSource {
378
395
chunk1.incrementInhabitedTime(j);
379
396
if (spawn && flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
380
397
++spawnChunkCount; // Folia - profiler
@@ -388,7 +405,7 @@ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..a50e6249eec7a8211b4674f34acd5d71
388
405
}
389
406
390
407
if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
391
- @@ -667,6 +679 ,36 @@ public class ServerChunkCache extends ChunkSource {
408
+ @@ -667,6 +680 ,36 @@ public class ServerChunkCache extends ChunkSource {
392
409
gameprofilerfiller.pop();
393
410
gameprofilerfiller.pop();
394
411
this.chunkMap.tick();
@@ -413,19 +430,19 @@ index b9b1dfe04eda8498f0ceff0aee66489d2a02b814..a50e6249eec7a8211b4674f34acd5d71
413
430
+ }
414
431
+
415
432
+ if (regionizedWorldData.lastAsyncSpawnStateTask == null || regionizedWorldData.lastAsyncSpawnStateTask.isDone()){
416
- + regionizedWorldData.lastAsyncSpawnStateTask = CompletableFuture.supplyAsync(() -> NaturalSpawner.createState(l, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true),regionizedWorldData.asyncMobSpawnExecutor );
433
+ + regionizedWorldData.lastAsyncSpawnStateTask = CompletableFuture.supplyAsync(() -> NaturalSpawner.createState(l, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true),RegionizedWorldData.ASYNC_MOB_SPAWNING_EXECUTOR );
417
434
+ }
418
435
+ } else {
419
436
+ if (regionizedWorldData.lastAsyncSpawnStateTask == null || regionizedWorldData.lastAsyncSpawnStateTask.isDone()){
420
- + regionizedWorldData.lastAsyncSpawnStateTask = CompletableFuture.supplyAsync(() -> NaturalSpawner.createState(l, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false),regionizedWorldData.asyncMobSpawnExecutor );
437
+ + regionizedWorldData.lastAsyncSpawnStateTask = CompletableFuture.supplyAsync(() -> NaturalSpawner.createState(l, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false), RegionizedWorldData.ASYNC_MOB_SPAWNING_EXECUTOR );
421
438
+ }
422
439
+ }
423
440
+ }
424
441
+ //Luminol end
425
442
}
426
443
}
427
444
428
- @@ -809,7 +851 ,7 @@ public class ServerChunkCache extends ChunkSource {
445
+ @@ -809,7 +852 ,7 @@ public class ServerChunkCache extends ChunkSource {
429
446
@VisibleForDebug
430
447
public NaturalSpawner.SpawnState getLastSpawnState() {
431
448
io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading
0 commit comments