mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-23 00:49:31 +00:00
316 lines
17 KiB
Diff
316 lines
17 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: wangxyper <wangxyper@163.com>
|
|
Date: Mon, 9 Jan 2023 09:26:38 +0800
|
|
Subject: [PATCH] Hearse: Update codes
|
|
|
|
Original license: MIT
|
|
Original project: https://github.com/NaturalCodeClub/HearseRewrite
|
|
|
|
diff --git a/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java b/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
|
|
index 06f55f26eb63e356b3558622bf68711f18cda1c6..2a43625d13d7aa253c15aba8092ac9361785a5f0 100644
|
|
--- a/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
|
|
+++ b/src/main/java/co/earthme/hearse/concurrent/WorkerThread.java
|
|
@@ -3,8 +3,11 @@ package co.earthme.hearse.concurrent;
|
|
import io.papermc.paper.util.TickThread;
|
|
|
|
public class WorkerThread extends TickThread {
|
|
+
|
|
public WorkerThread(String name) {
|
|
super(name);
|
|
+ this.setDaemon(true);
|
|
+ this.setPriority(Thread.NORM_PRIORITY - 2);
|
|
}
|
|
|
|
public static boolean isWorker(){
|
|
diff --git a/src/main/java/co/earthme/hearse/concurrent/WorkerThreadFactory.java b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadFactory.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e65b1eba68003a9f7ce5080d07a521817831ff48
|
|
--- /dev/null
|
|
+++ b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadFactory.java
|
|
@@ -0,0 +1,5 @@
|
|
+package co.earthme.hearse.concurrent;
|
|
+
|
|
+public interface WorkerThreadFactory {
|
|
+ WorkerThread getNewThread(Runnable task);
|
|
+}
|
|
diff --git a/src/main/java/co/earthme/hearse/concurrent/ThreadPool.java b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
|
|
similarity index 62%
|
|
rename from src/main/java/co/earthme/hearse/concurrent/ThreadPool.java
|
|
rename to src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
|
|
index 3fbc81cb880cf6d38bb4c940b4cc1fa828c2ef17..f7ca6d650d9089b65137d61acca64c89e5b4db22 100644
|
|
--- a/src/main/java/co/earthme/hearse/concurrent/ThreadPool.java
|
|
+++ b/src/main/java/co/earthme/hearse/concurrent/WorkerThreadPoolExecutor.java
|
|
@@ -6,25 +6,17 @@ import java.util.Queue;
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.locks.LockSupport;
|
|
|
|
-public class ThreadPool extends ThreadPoolExecutor {
|
|
- public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue) {
|
|
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
|
|
- }
|
|
-
|
|
- public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull ThreadFactory threadFactory) {
|
|
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
|
|
- }
|
|
+public class WorkerThreadPoolExecutor extends ThreadPoolExecutor {
|
|
+ private final Queue<TaskEntry> taskEntries = new ConcurrentLinkedQueue<>();
|
|
|
|
- public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull RejectedExecutionHandler handler) {
|
|
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
|
|
+ public WorkerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull WorkerThreadFactory workerThreadFactory) {
|
|
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,r->workerThreadFactory.getNewThread(r));
|
|
}
|
|
|
|
- public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull ThreadFactory threadFactory, @NotNull RejectedExecutionHandler handler) {
|
|
- super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
|
|
+ public WorkerThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NotNull TimeUnit unit, @NotNull BlockingQueue<Runnable> workQueue, @NotNull WorkerThreadFactory workerThreadFactory, @NotNull RejectedExecutionHandler handler) {
|
|
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,r->workerThreadFactory.getNewThread(r), handler);
|
|
}
|
|
|
|
- private final Queue<TaskEntry> taskEntries = new ConcurrentLinkedQueue<>();
|
|
-
|
|
public void executeWithSubTask(Runnable mainTask,Runnable subTask){
|
|
final TaskEntry wrapped = new TaskEntry(subTask,mainTask);
|
|
this.taskEntries.offer(wrapped);
|
|
diff --git a/src/main/java/co/earthme/hearse/server/ServerHook.java b/src/main/java/co/earthme/hearse/server/ServerHook.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..22260735664d986fed6bf82e4016b647417e1932
|
|
--- /dev/null
|
|
+++ b/src/main/java/co/earthme/hearse/server/ServerHook.java
|
|
@@ -0,0 +1,66 @@
|
|
+package co.earthme.hearse.server;
|
|
+
|
|
+import co.earthme.hearse.concurrent.WorkerThread;
|
|
+import co.earthme.hearse.concurrent.WorkerThreadPoolExecutor;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.world.entity.Entity;
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
+import java.util.concurrent.TimeUnit;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+
|
|
+public class ServerHook {
|
|
+ private static volatile boolean firstTick = false;
|
|
+ private static final AtomicInteger threadId = new AtomicInteger();
|
|
+ private static final WorkerThreadPoolExecutor worker = new WorkerThreadPoolExecutor(
|
|
+ Runtime.getRuntime().availableProcessors(),
|
|
+ Runtime.getRuntime().availableProcessors(),
|
|
+ 100,
|
|
+ TimeUnit.MILLISECONDS,
|
|
+ new LinkedBlockingQueue<>(),
|
|
+ task -> {
|
|
+ WorkerThread workerThread = new WorkerThread("Hearse-Worker-Thread # "+threadId.getAndIncrement());
|
|
+ return workerThread;
|
|
+ }
|
|
+ );
|
|
+
|
|
+ public static void executeAsyncTask(Runnable task){
|
|
+ worker.execute(task);
|
|
+ }
|
|
+
|
|
+ public static void executeAsyncTaskWithMainThreadCallback(Runnable task,Runnable callBack){
|
|
+ worker.executeWithSubTask(task,callBack);
|
|
+ }
|
|
+
|
|
+ public static void callPostTick(){
|
|
+ if (!firstTick){
|
|
+ firstTick = true;
|
|
+ return;
|
|
+ }
|
|
+ worker.runAllSubTasks();
|
|
+ }
|
|
+
|
|
+ public static void callAsyncEntityTick(Entity entity, ServerLevel level){
|
|
+ MinecraftServer.getServer().executeMidTickTasks();
|
|
+ worker.execute(()->{
|
|
+ entity.activatedPriorityReset = false;
|
|
+ if (!entity.isRemoved()) {
|
|
+ entity.checkDespawn();
|
|
+ Entity entity1 = entity.getVehicle();
|
|
+ if (entity1 != null) {
|
|
+ if (!entity1.isRemoved() && entity1.hasPassenger(entity)) {
|
|
+ return;
|
|
+ }
|
|
+ entity.stopRiding();
|
|
+ }
|
|
+ try {
|
|
+ level.tickNonPassenger(entity);
|
|
+ } catch (Throwable throwable) {
|
|
+ if (throwable instanceof ThreadDeath) throw throwable;
|
|
+ level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(throwable.getMessage(), throwable)));
|
|
+ throwable.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index 3b7e4b724e86518ea57f5ed5ef0b8b3741d10f6f..e0e169a4403926ff6be004de1bf5ec2079acb440 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -1,5 +1,6 @@
|
|
package net.minecraft.server;
|
|
|
|
+import co.earthme.hearse.server.ServerHook;
|
|
import com.google.common.base.Splitter;
|
|
import com.google.common.collect.ImmutableList;
|
|
import co.aikar.timings.Timings;
|
|
@@ -1407,6 +1408,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
|
|
++this.tickCount;
|
|
this.tickChildren(shouldKeepTicking);
|
|
+ ServerHook.callPostTick();
|
|
if (i - this.lastServerStatus >= 5000000000L) {
|
|
this.lastServerStatus = i;
|
|
this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount()));
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index a2935994edc279d880ff26dd5cc4e33f1105acc8..81697ea6d00967852556c3bb741317db030c24db 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -833,12 +833,10 @@ public class ServerChunkCache extends ChunkSource {
|
|
if (chunkMap.playerMobDistanceMap != null && _pufferfish_spawnCountsReady.getAndSet(false)) {
|
|
net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> {
|
|
int mapped = distanceManager.getNaturalSpawnChunkCount();
|
|
- io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<Entity> objectiterator =
|
|
- level.entityTickList.entities.iterator(io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS);
|
|
+ Iterator<Entity> objectiterator = level.entityTickList.entities.iterator();
|
|
gg.pufferfish.pufferfish.util.IterableWrapper<Entity> wrappedIterator =
|
|
new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator);
|
|
lastSpawnState = NaturalSpawner.createState(mapped, wrappedIterator, this::getFullChunk, null, true);
|
|
- objectiterator.finishedIterating();
|
|
_pufferfish_spawnCountsReady.set(true);
|
|
});
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
index 6074956d677542a46066dc45ceda9d73a2e09d27..125e5fb54acb68d58ea9fb973894b02facb04edc 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
@@ -1,6 +1,8 @@
|
|
package net.minecraft.server.level;
|
|
|
|
import co.aikar.timings.TimingHistory;
|
|
+import co.earthme.hearse.concurrent.WorkerThread;
|
|
+import co.earthme.hearse.server.ServerHook;
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Sets;
|
|
@@ -221,7 +223,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
|
|
public final void loadChunksForMoveAsync(AABB axisalignedbb, ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority priority,
|
|
java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
|
|
- if (Thread.currentThread() != this.thread) {
|
|
+ if (Thread.currentThread() != this.thread && !WorkerThread.isWorker()) {
|
|
this.getChunkSource().mainThreadProcessor.execute(() -> {
|
|
this.loadChunksForMoveAsync(axisalignedbb, priority, onLoad);
|
|
});
|
|
@@ -643,71 +645,15 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
//timings.doSounds.stopTiming(); // Spigot // Purpur
|
|
this.handlingTick = false;
|
|
//gameprofilerfiller.pop(); // Purpur
|
|
- boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
|
|
-
|
|
- if (flag) {
|
|
- this.resetEmptyTime();
|
|
- }
|
|
-
|
|
- if (flag || this.emptyTime++ < 300) {
|
|
- //gameprofilerfiller.push("entities"); // Purpur
|
|
- //timings.tickEntities.startTiming(); // Spigot // Purpur
|
|
- if (this.dragonFight != null) {
|
|
- //gameprofilerfiller.push("dragonFight"); // Purpur
|
|
- this.dragonFight.tick();
|
|
- //gameprofilerfiller.pop(); // Purpur
|
|
- }
|
|
-
|
|
- org.spigotmc.ActivationRange.activateEntities(this); // Spigot
|
|
- //timings.entityTick.startTiming(); // Spigot // Purpur
|
|
- this.entityTickList.forEach((entity) -> {
|
|
- entity.activatedPriorityReset = false; // Pufferfish - DAB
|
|
- if (!entity.isRemoved()) {
|
|
- if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
|
|
- entity.discard();
|
|
- } else {
|
|
- //gameprofilerfiller.push("checkDespawn"); // Purpur
|
|
- entity.checkDespawn();
|
|
- //gameprofilerfiller.pop(); // Purpur
|
|
- if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list
|
|
- Entity entity1 = entity.getVehicle();
|
|
-
|
|
- if (entity1 != null) {
|
|
- if (!entity1.isRemoved() && entity1.hasPassenger(entity)) {
|
|
- return;
|
|
- }
|
|
-
|
|
- entity.stopRiding();
|
|
- }
|
|
-
|
|
- //gameprofilerfiller.push("tick"); // Purpur
|
|
- // Pufferfish start - copied from this.guardEntityTick
|
|
- try {
|
|
- this.tickNonPassenger(entity); // Pufferfish - changed
|
|
- MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
|
|
- } catch (Throwable throwable) {
|
|
- if (throwable instanceof ThreadDeath) throw throwable; // Paper
|
|
- // Paper start - Prevent tile entity and entity crashes
|
|
- final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level.getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
|
|
- MinecraftServer.LOGGER.error(msg, throwable);
|
|
- getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable)));
|
|
- entity.discard();
|
|
- // Paper end
|
|
- }
|
|
- // Pufferfish end
|
|
- //gameprofilerfiller.pop(); // Purpur
|
|
- }
|
|
- }
|
|
- }
|
|
- });
|
|
- //timings.entityTick.stopTiming(); // Spigot // Purpur
|
|
- //timings.tickEntities.stopTiming(); // Spigot // Purpur
|
|
- //gameprofilerfiller.pop(); // Purpur
|
|
- this.tickBlockEntities();
|
|
+ this.resetEmptyTime();
|
|
+ if (this.dragonFight != null) {
|
|
+ this.dragonFight.tick();
|
|
}
|
|
-
|
|
- //gameprofilerfiller.push("entityManagement"); // Purpur
|
|
- //this.entityManager.tick(); // Paper - rewrite chunk system
|
|
+ org.spigotmc.ActivationRange.activateEntities(this); // Spigot
|
|
+ this.entityTickList.forEach((entity) -> {
|
|
+ ServerHook.callAsyncEntityTick(entity,this);
|
|
+ });
|
|
+ this.tickBlockEntities();
|
|
}
|
|
|
|
@Override
|
|
@@ -746,7 +692,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
|
|
|
}
|
|
|
|
- private boolean shouldDiscardEntity(Entity entity) {
|
|
+ public boolean shouldDiscardEntity(Entity entity) {
|
|
return !this.server.isSpawningAnimals() && (entity instanceof Animal || entity instanceof WaterAnimal) ? true : !this.server.areNpcsEnabled() && entity instanceof Npc;
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 958e0ee29915bddde2cb8ebfd578448b83e2b149..de78c5bdde53b4adfed9fda4d473560849bdb5aa 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -2,6 +2,7 @@ package net.minecraft.world.level;
|
|
|
|
import co.aikar.timings.Timing;
|
|
import co.aikar.timings.Timings;
|
|
+import co.earthme.hearse.concurrent.WorkerThread;
|
|
import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
|
import com.destroystokyo.paper.exception.ServerInternalException;
|
|
import com.google.common.base.MoreObjects;
|
|
@@ -1116,7 +1117,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
}
|
|
// Paper end
|
|
// CraftBukkit end
|
|
- return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && !io.papermc.paper.util.TickThread.isTickThread() ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); // Paper - rewrite chunk system
|
|
+ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && !io.papermc.paper.util.TickThread.isTickThread() && !WorkerThread.isWorker() ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); // Paper - rewrite chunk system
|
|
}
|
|
|
|
public void setBlockEntity(BlockEntity blockEntity) {
|