9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00
Files
Leaf/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch
hayanesuru ff9e4f506b optimize tracker (#323)
* optimize tracker

* optimize scaledRange

* cleanup

* fix loop

* fix loop

* optimize AttributeMap

* optimize TrackedEntity#seenBy

* revert packDirty

* cleanup
2025-05-17 15:10:27 +03:00

105 lines
5.9 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 379c2dc1853e45a96dda9b13bf28b7e08f65658a..361f4de9cdf0f7505628a2fed2a3f5366031e04b 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.");
}
// Leaves start - skip photographer
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index edcd209798740f31cb302f36d7864a0d8ea1d561..e2444cc9e28dd432bf3351066b1408102decfa0a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -749,7 +749,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
players.add(connection.getPlayer().getBukkitEntity());
}
}
@@ -1057,7 +1057,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// Paper start - resend possibly desynced entity instead of add entity packet
- for (final ServerPlayerConnection connection : entityTracker.seenBy) {
+ for (final ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf
this.getHandle().resendPossiblyDesyncedEntityData(connection.getPlayer());
}
// Paper end - resend possibly desynced entity instead of add entity packet
@@ -1245,7 +1245,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
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
}
return set;
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e52479f3c888268fd1febeb78e9965af834a8ae9..c2552c3706831f7012b5b449fa43c7d5990056a4 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1973,6 +1973,26 @@ public class CraftEventFactory {
}
public static boolean handleBlockFormEvent(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block, int flag, @Nullable Entity entity) {
+ // 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(() -> {
+ CraftBlockState blockState = CraftBlockStates.getBlockState(world, pos, flag);
+ blockState.setData(block);
+
+ BlockFormEvent event = (entity == null) ? new BlockFormEvent(blockState.getBlock(), blockState) : new EntityBlockFormEvent(entity.getBukkitEntity(), blockState.getBlock(), blockState);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ blockState.update(true);
+ }
+
+ future.complete(!event.isCancelled());
+ });
+
+ return future.join();
+ }
+ // Leaf end - Multithreaded tracker
CraftBlockState blockState = CraftBlockStates.getBlockState(world, pos, flag);
blockState.setData(block);