9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 01:49:16 +00:00

Updated Upstream (Hearse)

This commit is contained in:
Dreeam
2023-01-13 08:14:58 -05:00
parent d507bf5a94
commit c6ccddf461
10 changed files with 454 additions and 1 deletions

View File

@@ -0,0 +1,223 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Thu, 12 Jan 2023 13:04:01 +0800
Subject: [PATCH] Hearse: Parallel world ticking
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java b/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
index 443ac5267245c20830692b37802afd6ebdf8813b..c26511c26bd02320a55a01168f342b4b051ffdfd 100644
--- a/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
+++ b/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
@@ -8,14 +8,16 @@ import java.util.concurrent.atomic.AtomicInteger;
public class DefaultWorkerFactory implements WorkerThreadFactory {
private static final AtomicInteger poolId = new AtomicInteger();
private final AtomicInteger threadId = new AtomicInteger();
+ private final String bound;
- public DefaultWorkerFactory(){
+ public DefaultWorkerFactory(String bound){
poolId.getAndIncrement();
+ this.bound = bound;
}
@Override
public WorkerThread getNewThread(Runnable task) {
- final WorkerThread workerThread = new WorkerThread(task,"pool-"+poolId.get()+"-worker-"+threadId.getAndIncrement());
+ final WorkerThread workerThread = new WorkerThread(task,"pool-"+poolId.get()+"-worker-"+threadId.getAndIncrement()+"-bound-"+this.bound);
if (workerThread.isDaemon()){
workerThread.setDaemon(false);
}
diff --git a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
index fd7912df03ae39347206fe8db2efa7a8a0e516c8..9d26ff7d07f1e972f1720f5b2d0e66d4c9c3f1e5 100644
--- a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
+++ b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
@@ -18,7 +18,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class ServerEntityTickHook {
private static final Logger logger = LogManager.getLogger();
private static volatile boolean firstTick = false;
- private static final WorkerThreadFactory defFactory = new DefaultWorkerFactory();
+ private static final WorkerThreadFactory defFactory = new DefaultWorkerFactory("entity");
private static final AtomicInteger threadId = new AtomicInteger();
private static WorkerThreadPoolExecutor worker;
private static boolean asyncEntityEnabled;
diff --git a/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java b/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java
new file mode 100644
index 0000000000000000000000000000000000000000..5670fdae5d16cbbdf605df048ae253208e49a82c
--- /dev/null
+++ b/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java
@@ -0,0 +1,70 @@
+package co.earthme.hearse.server;
+
+import co.earthme.hearse.Hearse;
+import co.earthme.hearse.HearseConfig;
+import co.earthme.hearse.concurrent.WorkerThreadPoolExecutor;
+import co.earthme.hearse.concurrent.threadfactory.DefaultWorkerFactory;
+import net.minecraft.CrashReport;
+import net.minecraft.ReportedException;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.LockSupport;
+import java.util.function.BooleanSupplier;
+
+public class ServerLevelTickHook {
+ private static final DefaultWorkerFactory workerFactory = new DefaultWorkerFactory("world");
+ private static WorkerThreadPoolExecutor worker;
+ private static boolean enabledParaWorld;
+ private static volatile boolean inited = false;
+ private static final AtomicInteger activeTaskCount = new AtomicInteger();
+
+ public static void initWorker(){
+ enabledParaWorld = HearseConfig.getBoolean("optimizations.enableparallelworldtick",true);
+ if (enabledParaWorld){
+ worker = new WorkerThreadPoolExecutor(
+ MinecraftServer.getServer().levels.size(),
+ MinecraftServer.getServer().levels.size(),
+ 0,
+ TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(),
+ workerFactory
+ );
+ worker.prestartAllCoreThreads();
+ Hearse.getWorkerManager().addWorker("world",worker);
+ }
+ inited = true;
+ }
+
+ public static boolean isInited(){
+ return inited;
+ }
+
+ public static void callWorldTick(ServerLevel worldserver, BooleanSupplier shouldKeepTicking){
+ activeTaskCount.getAndIncrement();
+ worker.execute(()->{
+ try {
+ try {
+ worldserver.tick(shouldKeepTicking);
+ for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) {
+ regionManager.recalculateRegions();
+ }
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ }
+ worldserver.explosionDensityCache.clear();
+ }finally {
+ activeTaskCount.getAndDecrement();
+ }
+ });
+ }
+
+ public static void awaitWorldTicKTasks(){
+ while (activeTaskCount.get() > 0){
+ LockSupport.parkNanos("Await world ticking",1000000);
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index fe47aff8654283aa6a17a36226aa9fc7f18f9886..57bae261ee1d6db734b38dd5f67dbce98c41fc1c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -3,6 +3,7 @@ package net.minecraft.server;
import co.earthme.hearse.Hearse;
import co.earthme.hearse.HearseConfig;
import co.earthme.hearse.server.ServerEntityTickHook;
+import co.earthme.hearse.server.ServerLevelTickHook;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -223,7 +224,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private String localIp;
private int port;
private final LayeredRegistryAccess<RegistryLayer> registries;
- private Map<ResourceKey<Level>, ServerLevel> levels;
+ public Map<ResourceKey<Level>, ServerLevel> levels;
private PlayerList playerList;
private volatile boolean running;
private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart
@@ -1121,6 +1122,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
Arrays.fill( recentTps, 20 );
long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop
lastTick = start - TICK_TIME; // Paper
+ ServerLevelTickHook.initWorker(); //Hearse
while (this.running) {
// Paper start - rewrite chunk system
// guarantee that nothing can stop the server from halting if it can at least still tick
@@ -1515,11 +1517,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
//MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper // Purpur
this.isIteratingOverLevels = true; // Paper
- Iterator iterator = this.getAllLevels().iterator(); // Paper - move down
- while (iterator.hasNext()) {
- ServerLevel worldserver = (ServerLevel) iterator.next();
- worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
- worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ for (ServerLevel worldserver : this.getAllLevels()) {
+ worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
/*this.profiler.push(() -> { // Purpur
@@ -1534,35 +1534,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// CraftBukkit end */
//this.profiler.push("tick"); // Purpur
-
- try {
- //worldserver.timings.doTick.startTiming(); // Spigot // Purpur
- worldserver.tick(shouldKeepTicking);
- // Paper start
- for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) {
- regionManager.recalculateRegions();
- }
- // Paper end
- //worldserver.timings.doTick.stopTiming(); // Spigot // Purpur
- } catch (Throwable throwable) {
- // Spigot Start
- CrashReport crashreport;
- try {
- crashreport = CrashReport.forThrowable(throwable, "Exception ticking world");
- } catch (Throwable t) {
- if (throwable instanceof ThreadDeath) { throw (ThreadDeath)throwable; } // Paper
- throw new RuntimeException("Error generating crash report", t);
- }
- // Spigot End
-
- worldserver.fillReportDetails(crashreport);
- throw new ReportedException(crashreport);
- }
-
- //this.profiler.pop(); // Purpur
- //this.profiler.pop(); // Purpur
- worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
+ ServerLevelTickHook.callWorldTick(worldserver,shouldKeepTicking);
}
+ ServerLevelTickHook.awaitWorldTicKTasks();
this.isIteratingOverLevels = false; // Paper
//this.profiler.popPush("connection"); // Purpur
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index de78c5bdde53b4adfed9fda4d473560849bdb5aa..4a75c2895f4f5e3229be3c7b177445611a1e70b6 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -7,6 +7,7 @@ import com.destroystokyo.paper.event.server.ServerExceptionEvent;
import com.destroystokyo.paper.exception.ServerInternalException;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.mojang.serialization.Codec;
import java.io.IOException;
import java.util.Iterator;
@@ -179,7 +180,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
private org.spigotmc.TickLimiter entityLimiter;
private org.spigotmc.TickLimiter tileLimiter;
private int tileTickPosition;
- public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = Maps.newConcurrentMap(); // Paper - Optimize explosions
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
// Paper start - fix and optimise world upgrading

View File

@@ -0,0 +1,102 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Thu, 12 Jan 2023 13:58:20 +0800
Subject: [PATCH] Hearse: Print world worker thread names when server started
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java b/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
index c26511c26bd02320a55a01168f342b4b051ffdfd..03a29509821a17faac2dc8ab810a2693b03bfbc6 100644
--- a/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
+++ b/src/main/java/co/earthme/hearse/concurrent/threadfactory/DefaultWorkerFactory.java
@@ -2,25 +2,38 @@ package co.earthme.hearse.concurrent.threadfactory;
import co.earthme.hearse.concurrent.WorkerThread;
import co.earthme.hearse.concurrent.WorkerThreadFactory;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+import it.unimi.dsi.fastutil.objects.ObjectLists;
import net.minecraft.server.MinecraftServer;
+
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class DefaultWorkerFactory implements WorkerThreadFactory {
private static final AtomicInteger poolId = new AtomicInteger();
private final AtomicInteger threadId = new AtomicInteger();
private final String bound;
+ private final List<Thread> createdThreads = ObjectLists.synchronize(new ObjectArrayList<>());
public DefaultWorkerFactory(String bound){
poolId.getAndIncrement();
this.bound = bound;
}
+ public List<Thread> getCreatedThreads() {
+ return this.createdThreads;
+ }
+
@Override
public WorkerThread getNewThread(Runnable task) {
- final WorkerThread workerThread = new WorkerThread(task,"pool-"+poolId.get()+"-worker-"+threadId.getAndIncrement()+"-bound-"+this.bound);
- if (workerThread.isDaemon()){
- workerThread.setDaemon(false);
- }
+ final WorkerThread workerThread = new WorkerThread(()->{
+ try {
+ task.run();
+ }finally {
+ this.createdThreads.remove(Thread.currentThread());
+ }
+ },"pool-"+poolId.get()+"-worker-"+threadId.getAndIncrement()+"-bound-"+this.bound);
+ this.createdThreads.add(workerThread);
workerThread.setDaemon(true);
workerThread.setPriority(Thread.NORM_PRIORITY - 2);
workerThread.setContextClassLoader(MinecraftServer.class.getClassLoader());
diff --git a/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java b/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java
index 5670fdae5d16cbbdf605df048ae253208e49a82c..8085eb700d8e5c20ebb5bfeceb78198c6e973019 100644
--- a/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java
+++ b/src/main/java/co/earthme/hearse/server/ServerLevelTickHook.java
@@ -2,12 +2,15 @@ package co.earthme.hearse.server;
import co.earthme.hearse.Hearse;
import co.earthme.hearse.HearseConfig;
+import co.earthme.hearse.concurrent.WorkerThread;
import co.earthme.hearse.concurrent.WorkerThreadPoolExecutor;
import co.earthme.hearse.concurrent.threadfactory.DefaultWorkerFactory;
import net.minecraft.CrashReport;
import net.minecraft.ReportedException;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -21,6 +24,7 @@ public class ServerLevelTickHook {
private static boolean enabledParaWorld;
private static volatile boolean inited = false;
private static final AtomicInteger activeTaskCount = new AtomicInteger();
+ private static final Logger logger = LogManager.getLogger();
public static void initWorker(){
enabledParaWorld = HearseConfig.getBoolean("optimizations.enableparallelworldtick",true);
@@ -28,13 +32,17 @@ public class ServerLevelTickHook {
worker = new WorkerThreadPoolExecutor(
MinecraftServer.getServer().levels.size(),
MinecraftServer.getServer().levels.size(),
- 0,
+ Long.MAX_VALUE,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
workerFactory
);
+ worker.allowCoreThreadTimeOut(true);
worker.prestartAllCoreThreads();
Hearse.getWorkerManager().addWorker("world",worker);
+ for (Thread worker : workerFactory.getCreatedThreads()){
+ logger.warn("World worker name:{}.This can help you to slove the lag problems when you using parallel world ticking",worker.getName());
+ }
}
inited = true;
}

View File

@@ -8,7 +8,7 @@ Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
index fd7912df03ae39347206fe8db2efa7a8a0e516c8..85f92f20718ae21bffd687e00614588c771cc940 100644
index 9d26ff7d07f1e972f1720f5b2d0e66d4c9c3f1e5..86f8afd54c0cbb449403c3f43e6880ade13cfecc 100644
--- a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
+++ b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
@@ -8,6 +8,7 @@ import co.earthme.hearse.concurrent.threadfactory.DefaultWorkerFactory;

View File

@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Fri, 13 Jan 2023 15:22:42 +0800
Subject: [PATCH] Hearse: Remove a NPE fix
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
index d6951b05128fea7eb5f1b40837cea77e0c209165..26e1b4060f2a93cb659170f83e6ce64086e0eb0c 100644
--- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
+++ b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java
@@ -423,10 +423,8 @@ public final class EntityLookup implements LevelEntityGetter<Entity> {
final ChunkEntitySlices old = this.getChunk(entity.sectionX, entity.sectionZ);
final ChunkEntitySlices slices = this.getOrCreateChunk(newSectionX, newSectionZ);
- if (old!=null){
- if (!old.removeEntity(entity, entity.sectionY)) {
- LOGGER.warn("Could not remove entity " + entity + " from its old chunk section (" + entity.sectionX + "," + entity.sectionY + "," + entity.sectionZ + ") since it was not contained in the section");
- }
+ if (!old.removeEntity(entity, entity.sectionY)) {
+ LOGGER.warn("Could not remove entity " + entity + " from its old chunk section (" + entity.sectionX + "," + entity.sectionY + "," + entity.sectionZ + ") since it was not contained in the section");
}
if (!slices.addEntity(entity, newSectionY)) {

View File

@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Fri, 13 Jan 2023 15:25:47 +0800
Subject: [PATCH] Hearse: Change something
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
index 86f8afd54c0cbb449403c3f43e6880ade13cfecc..c0e7a9cf79ddf00827daba0aa9c7a32fa76b0c7c 100644
--- a/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
+++ b/src/main/java/co/earthme/hearse/server/ServerEntityTickHook.java
@@ -88,7 +88,7 @@ public class ServerEntityTickHook {
}
}
};
- if (!asyncEntityEnabled || entity instanceof Player){
+ if (!asyncEntityEnabled){
task.run();
return;
}

View File

@@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Fri, 13 Jan 2023 15:49:11 +0800
Subject: [PATCH] Hearse: Add new command
Original license: MIT
Original project: https://github.com/NaturalCodeClub/HearseRewrite
diff --git a/src/main/java/co/earthme/hearse/Hearse.java b/src/main/java/co/earthme/hearse/Hearse.java
index 79116449c221e0748e938f40366af03f93a4ab9f..692fef51b2f15dd1ddc28773a381b9da3b42725e 100644
--- a/src/main/java/co/earthme/hearse/Hearse.java
+++ b/src/main/java/co/earthme/hearse/Hearse.java
@@ -1,5 +1,6 @@
package co.earthme.hearse;
+import co.earthme.hearse.commands.EntityCountCommand;
import co.earthme.hearse.commands.WorkerCommand;
import co.earthme.hearse.server.ServerEntityTickHook;
import co.earthme.hearse.workers.WorkerThreadPoolManager;
@@ -12,6 +13,7 @@ public class Hearse {
HearseConfig.init();
ServerEntityTickHook.init();
MinecraftServer.getServer().server.getCommandMap().register("workers","hearse",new WorkerCommand());
+ MinecraftServer.getServer().server.getCommandMap().register("entitycount","hearse",new EntityCountCommand());
}
public static void onServerStop(){
diff --git a/src/main/java/co/earthme/hearse/commands/EntityCountCommand.java b/src/main/java/co/earthme/hearse/commands/EntityCountCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..563485b8c657a7a96ff3a391c8fa19159e6dd8f6
--- /dev/null
+++ b/src/main/java/co/earthme/hearse/commands/EntityCountCommand.java
@@ -0,0 +1,36 @@
+package co.earthme.hearse.commands;
+
+import com.google.common.collect.Maps;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.entity.Entity;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import java.util.Map;
+
+public class EntityCountCommand extends Command {
+ public EntityCountCommand() {
+ super("entitycount");
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
+ final Map<String,Integer> counts = Maps.newHashMap();
+ for (ServerLevel level : MinecraftServer.getServer().getAllLevels()){
+ for (Entity entity : level.entityTickList.entities){
+ final String name = entity.getType().getName();
+ if (!counts.containsKey(name)){
+ counts.put(name,0);
+ }
+ counts.replace(name,counts.get(name));
+ }
+ }
+ sender.sendMessage("Exists entity Counts:");
+ for (Map.Entry<String,Integer> entry : counts.entrySet()){
+ sender.sendMessage(ChatColor.BLUE+String.format("%s:%s",entry.getKey(),entry.getValue()));
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index ac92d1b36590bcc491d56a1eb442477c8f6e2d11..39c3aaf91514bd8a2f9f04496e25a6253442939f 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -146,7 +146,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
public final ServerChunkCache chunkSource;
private final MinecraftServer server;
public final PrimaryLevelData serverLevelData; // CraftBukkit - type
- final EntityTickList entityTickList;
+ public final EntityTickList entityTickList;
//public final PersistentEntitySectionManager<Entity> entityManager; // Paper - rewrite chunk system
private final GameEventDispatcher gameEventDispatcher;
public boolean noSave;