9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-22 08:29:28 +00:00
Files
Leaf/leaf-server/paper-patches/features/0042-Multithreaded-Tracker.patch
2025-06-03 07:23:43 +08:00

118 lines
6.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: peaches94 <peachescu94@gmail.com>
Date: Sat, 2 Jul 2022 00:35:56 -0500
Subject: [PATCH] Multithreaded Tracker
Original license: GPL v3
Original project: https://github.com/Bloom-host/Petal
Original license: GPL v3
Original project: https://github.com/TECHNOVE/Airplane-Experimental
Co-authored-by: Paul Sauve <paul@technove.co>
Co-authored-by: Kevin Raneri <kevin.raneri@gmail.com>
Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
This patch refactored from original multithreaded tracker (Petal version),
and is derived from the Airplane fork by Paul Sauve, the tree is like:
Airplane -> Pufferfish? -> Petal -> Leaf
We made much of tracking logic asynchronously, and fixed visible issue
for the case of some NPC plugins which using real entity type, e.g. Citizens.
But it is still recommending to use those packet based, virtual entity
based NPC plugins, e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc.
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
index db031298c2090eb36032de4b52335c62186e4cfb..84905d7802f8a5c3f68e15f1b17ef08216ad1f4e 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -42,6 +42,12 @@ class PaperEventManager {
if (event.isAsynchronous() && this.server.isPrimaryThread()) {
throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously.");
} else if (!event.isAsynchronous() && !this.server.isPrimaryThread() && !this.server.isStopping()) {
+ // Leaf start - Multithreaded tracker
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(event::callEvent);
+ return;
+ }
+ // Leaf end - Multithreaded tracker
throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously.");
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 2a63e8e725fa97da5d4b9fba6bfe19377c7cfbe1..0c286eabd8e4d5e599d93a151874af6bf3642265 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -758,7 +758,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
ChunkMap.TrackedEntity entityTracker = world.getChunkSource().chunkMap.entityMap.get(this.getEntityId());
if (entityTracker != null) {
- for (ServerPlayerConnection connection : entityTracker.seenBy) {
+ for (ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf - Multithreaded tracker
players.add(connection.getPlayer().getBukkitEntity());
}
}
@@ -1074,7 +1074,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return;
}
- for (final ServerPlayerConnection connection : entityTracker.seenBy) {
+ for (final ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf - Multithreaded tracker
this.getHandle().resendPossiblyDesyncedEntityData(connection.getPlayer());
}
}
@@ -1221,7 +1221,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
Set<org.bukkit.entity.Player> set = new java.util.HashSet<>(tracker.seenBy.size());
- for (net.minecraft.server.network.ServerPlayerConnection connection : tracker.seenBy) {
+ for (net.minecraft.server.network.ServerPlayerConnection connection : tracker.seenBy()) { // Leaf - Multithreaded tracker
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
}
return set;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index cab15624afaeaca5d69206a0b7fff5da54e5ef29..4533fbbbc35ed92177f7704f243a1614a1773ca1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2892,7 +2892,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Iterator<AttributeInstance> iterator = collection.iterator();
while (iterator.hasNext()) {
AttributeInstance genericInstance = iterator.next();
- if (genericInstance.getAttribute() == Attributes.MAX_HEALTH) {
+ if (genericInstance != null && genericInstance.getAttribute() == Attributes.MAX_HEALTH) { // Leaf - Multithreaded tracker
iterator.remove();
break;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 5300a513a295d472752d31a6e8af48bb64b06704..fec0f3b72c1808c5019e95760e3fef19c45e1be0 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1751,6 +1751,26 @@ public class CraftEventFactory {
}
public static boolean handleBlockFormEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, int flags, @Nullable Entity entity, boolean checkSetResult) {
+ // Leaf start - Multithreaded tracker
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled && Thread.currentThread() instanceof org.dreeam.leaf.async.tracker.MultithreadedTracker.MultithreadedTrackerThread) {
+ java.util.concurrent.CompletableFuture<Boolean> future = new java.util.concurrent.CompletableFuture<>();
+ net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> {
+ boolean resultFlag = false;
+ CraftBlockState snapshot = CraftBlockStates.getBlockState(world, pos);
+ snapshot.setData(state);
+
+ BlockFormEvent event = (entity == null) ? new BlockFormEvent(snapshot.getBlock(), snapshot) : new EntityBlockFormEvent(entity.getBukkitEntity(), snapshot.getBlock(), snapshot);
+ if (event.callEvent()) {
+ boolean result = snapshot.place(flags);
+ resultFlag = !checkSetResult || result;
+ }
+
+ future.complete(resultFlag);
+ });
+
+ return future.join();
+ }
+ // Leaf end - Multithreaded tracker
CraftBlockState snapshot = CraftBlockStates.getBlockState(world, pos);
snapshot.setData(state);