mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-29 03:49:21 +00:00
Some paper patches work
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrPowerGamerBR <git@mrpowergamerbr.com>
|
||||
Date: Sun, 19 Nov 2023 12:35:16 -0300
|
||||
Subject: [PATCH] SparklyPaper: Skip EntityScheduler's executeTick checks if
|
||||
there isn't any tasks to be run
|
||||
|
||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||
|
||||
On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, due to the thread checks, and because it needs to iterate all entities in all worlds.
|
||||
|
||||
To avoid the hefty ArrayDeque's size() call, we check if we *really* need to execute the executeTick, by adding all entities with scheduled tasks to a global set.
|
||||
|
||||
Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay).
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
||||
index c03608fec96b51e1867f43d8f42e5aefb1520e46..56268cf8d184e0b6cd46de8c2e893ad3da8ec64f 100644
|
||||
--- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
||||
+++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
||||
@@ -36,6 +36,7 @@ public final class EntityScheduler {
|
||||
* The Entity. Note that it is the CraftEntity, since only that class properly tracks world transfers.
|
||||
*/
|
||||
public final CraftEntity entity;
|
||||
+ public final net.minecraft.server.MinecraftServer server; // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
|
||||
private static final record ScheduledTask(Consumer<? extends Entity> run, Consumer<? extends Entity> retired) {}
|
||||
|
||||
@@ -46,7 +47,8 @@ public final class EntityScheduler {
|
||||
|
||||
private final ArrayDeque<ScheduledTask> currentlyExecuting = new ArrayDeque<>();
|
||||
|
||||
- public EntityScheduler(final CraftEntity entity) {
|
||||
+ public EntityScheduler(final net.minecraft.server.MinecraftServer server, final CraftEntity entity) { // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
+ this.server = Validate.notNull(server);
|
||||
this.entity = Validate.notNull(entity);
|
||||
}
|
||||
|
||||
@@ -61,14 +63,16 @@ public final class EntityScheduler {
|
||||
* @throws IllegalStateException If the scheduler is already retired.
|
||||
*/
|
||||
public void retire() {
|
||||
+ final Entity thisEntity = this.entity.getHandleRaw(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
synchronized (this.stateLock) {
|
||||
if (this.tickCount == RETIRED_TICK_COUNT) {
|
||||
throw new IllegalStateException("Already retired");
|
||||
}
|
||||
this.tickCount = RETIRED_TICK_COUNT;
|
||||
+ this.server.entitiesWithScheduledTasks.remove(thisEntity); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
}
|
||||
|
||||
- final Entity thisEntity = this.entity.getHandleRaw();
|
||||
+ //final Entity thisEntity = this.entity.getHandleRaw(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (moved up)
|
||||
|
||||
// correctly handle and order retiring while running executeTick
|
||||
for (int i = 0, len = this.currentlyExecuting.size(); i < len; ++i) {
|
||||
@@ -124,6 +128,7 @@ public final class EntityScheduler {
|
||||
if (this.tickCount == RETIRED_TICK_COUNT) {
|
||||
return false;
|
||||
}
|
||||
+ this.server.entitiesWithScheduledTasks.add(this.entity.getHandleRaw()); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
this.oneTimeDelayed.computeIfAbsent(this.tickCount + Math.max(1L, delay), (final long keyInMap) -> {
|
||||
return new ArrayList<>();
|
||||
}).add(task);
|
||||
@@ -143,6 +148,13 @@ public final class EntityScheduler {
|
||||
TickThread.ensureTickThread(thisEntity, "May not tick entity scheduler asynchronously");
|
||||
final List<ScheduledTask> toRun;
|
||||
synchronized (this.stateLock) {
|
||||
+ // SparklyPaper start - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
+ // Do we *really* have scheduled tasks tho?
|
||||
+ if (this.currentlyExecuting.isEmpty() && this.oneTimeDelayed.isEmpty()) { // Check if we have any pending tasks and, if not, skip!
|
||||
+ this.server.entitiesWithScheduledTasks.remove(thisEntity); // We don't! Bye bye!!
|
||||
+ return;
|
||||
+ }
|
||||
+ // SparklyPaper end
|
||||
if (this.tickCount == RETIRED_TICK_COUNT) {
|
||||
throw new IllegalStateException("Ticking retired scheduler");
|
||||
}
|
||||
@@ -178,4 +190,12 @@ public final class EntityScheduler {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaf start - SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
+ public boolean hasTasks() {
|
||||
+ synchronized (this.stateLock) {
|
||||
+ return !this.currentlyExecuting.isEmpty() || !this.oneTimeDelayed.isEmpty();
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end - SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 5aa8eab78e99408b0beb64d7ed07ff1bc61541db..0809ed41274be3dd18eb89aa96c442bc3995f1b7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -80,7 +80,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftEntity.DATA_TYPE_REGISTRY);
|
||||
protected net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
||||
// Paper start - Folia shedulers
|
||||
- public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this);
|
||||
+ public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler; // = new io.papermc.paper.threadedregions.EntityScheduler(this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
private final io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler apiScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler(this);
|
||||
|
||||
@Override
|
||||
@@ -93,6 +93,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
this.server = server;
|
||||
this.entity = entity;
|
||||
this.entityType = CraftEntityType.minecraftToBukkit(entity.getType());
|
||||
+ this.taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this.entity.getServer(), this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
}
|
||||
|
||||
public static <T extends Entity> CraftEntity getEntity(CraftServer server, T entity) {
|
||||
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrPowerGamerBR <git@mrpowergamerbr.com>
|
||||
Date: Thu, 23 Nov 2023 14:36:47 -0300
|
||||
Subject: [PATCH] SparklyPaper: Optimize "canSee" checks
|
||||
|
||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||
|
||||
The "canSee" checks is in a hot path, invoked by each entity for each player on the server if they are in tracking range, so optimizing it is pretty nice
|
||||
|
||||
First, we change the original "HashMap" to fastutil's "Object2ObjectOpenHashMap", because the containsKey throughput is better
|
||||
|
||||
Then, we add a "isEmpty()" check before attempting to check if the map contains something
|
||||
|
||||
This seems stupid, but it does seem that it improves the performance a bit, and it makes sense, "containsKey(...)" does not attempt to check the map size before attempting to check if the map contains the key
|
||||
|
||||
We also create a "canSee" method tailored for "ChunkMap#updatePlayer()", a method without the equals check (the "updatePlayer()" already checks if the entity is the same entity) because the CraftPlayer's `equals()` check is a *bit* expensive compared to only checking the object's identity, and because the identity has already been check, we don't need to check it twice.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 905cea7470f7bb8dee27bbfc4d267d46c28fe21b..ff0ef4e148c85aff18094a139705de5034d99e20 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -212,7 +212,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
private boolean hasPlayedBefore = false;
|
||||
private final ConversationTracker conversationTracker = new ConversationTracker();
|
||||
private final Set<String> channels = new HashSet<String>();
|
||||
- private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
|
||||
+ private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // SparklyPaper - optimize canSee checks
|
||||
private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
|
||||
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
|
||||
private int hash = 0;
|
||||
@@ -2266,9 +2266,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public boolean canSee(org.bukkit.entity.Entity entity) {
|
||||
- return this.equals(entity) || entity.isVisibleByDefault() ^ this.invertedVisibilityEntities.containsKey(entity.getUniqueId()); // SPIGOT-7312: Can always see self
|
||||
+ return this.equals(entity) || entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks
|
||||
}
|
||||
|
||||
+ // SparklyPaper - optimize canSee checks
|
||||
+ // The check in ChunkMap#updatePlayer already rejects if it is the same entity, so we don't need to check it twice, especially because CraftPlayer's equals check is a bit expensive
|
||||
+ public boolean canSeeChunkMapUpdatePlayer(org.bukkit.entity.Entity entity) {
|
||||
+ return entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks
|
||||
+ }
|
||||
+ // SparklyPaper end
|
||||
+
|
||||
public boolean canSeePlayer(UUID uuid) {
|
||||
org.bukkit.entity.Entity entity = this.getServer().getPlayer(uuid);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Sat, 24 Feb 2024 01:16:07 -0500
|
||||
Subject: [PATCH] Including 5s in getTPS()
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 704b5fd8c10cdc5363f59fbd878d9453926d91c3..540c84579ef57ec73bc5250ff889139ddcdf296b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2987,6 +2987,8 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public double[] getTPS() {
|
||||
+ if (org.dreeam.leaf.config.modules.misc.Including5sIngetTPS.enabled) return getTPSIncluding5SecondAverage(); // Leaf - Including 5s in getTPS()
|
||||
+
|
||||
return new double[] {
|
||||
net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(),
|
||||
net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(),
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Mon, 26 Feb 2024 18:51:02 -0500
|
||||
Subject: [PATCH] Don't throw exception on missing ResourceKey value
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryValueSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryValueSerializer.java
|
||||
index 6831b7b72c5e1f79eff36019ca2ff56531c26df8..a1b9949c9e36770724292ea2f71f21456ae7889f 100644
|
||||
--- a/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryValueSerializer.java
|
||||
+++ b/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryValueSerializer.java
|
||||
@@ -23,7 +23,11 @@ public final class RegistryValueSerializer<T> extends RegistryEntrySerializer<T,
|
||||
protected T convertFromResourceKey(ResourceKey<T> key) throws SerializationException {
|
||||
final T value = this.registry().getValue(key);
|
||||
if (value == null) {
|
||||
- throw new SerializationException("Missing value in " + this.registry() + " with key " + key.location());
|
||||
+ // Leaf start - Don't throw exception on missing ResourceKey value
|
||||
+ //throw new SerializationException("Missing value in " + this.registry() + " with key " + key.location());
|
||||
+ com.mojang.logging.LogUtils.getClassLogger().error("Missing value in {} with key {}", this.registry(), key.location());
|
||||
+ return null;
|
||||
+ // Leaf end - Don't throw exception on missing ResourceKey value
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalfinals <yuu8583@proton.me>
|
||||
Date: Tue, 12 Mar 2024 00:36:29 +0800
|
||||
Subject: [PATCH] Virtual Thread for async scheduler
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
index 0ca279fb71d39c81b1f608e0ee9ba3e498d55fa3..1aaccc688d246201db141a0d5e2c68d0dd4069b2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
@@ -38,17 +38,40 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CraftAsyncScheduler extends CraftScheduler {
|
||||
|
||||
- private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
|
||||
- 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(),
|
||||
- new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build());
|
||||
+ private final org.apache.logging.log4j.Logger LOGGER = org.apache.logging.log4j.LogManager.getLogger(getClass().getName()); // Leaf - Class logger
|
||||
+ private final Executor executor; // Leaf - use super class
|
||||
private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
|
||||
.setNameFormat("Craft Async Scheduler Management Thread").build());
|
||||
private final List<CraftTask> temp = new ArrayList<>();
|
||||
|
||||
CraftAsyncScheduler() {
|
||||
super(true);
|
||||
- executor.allowCoreThreadTimeOut(true);
|
||||
- executor.prestartAllCoreThreads();
|
||||
+
|
||||
+ // Leaf start - Ability to use Virtual Thread for async scheduler
|
||||
+ if (org.dreeam.leaf.config.modules.opt.VT4BukkitScheduler.enabled) {
|
||||
+ executor = new ThreadPoolExecutor(
|
||||
+ 0, Integer.MAX_VALUE, 10L, TimeUnit.SECONDS, new SynchronousQueue<>(), // Use 10s for keepalive time
|
||||
+ Thread.ofVirtual()
|
||||
+ .name("Craft Scheduler Thread - ", 0)
|
||||
+ .uncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER))
|
||||
+ .factory()
|
||||
+ );
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ executor = new ThreadPoolExecutor(
|
||||
+ 4, Integer.MAX_VALUE, 30L, TimeUnit.SECONDS, new SynchronousQueue<>(),
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("Craft Scheduler Thread - %1$d")
|
||||
+ .setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER))
|
||||
+ .build());
|
||||
+
|
||||
+ var threadPoolExecutor = (ThreadPoolExecutor) executor;
|
||||
+
|
||||
+ threadPoolExecutor.allowCoreThreadTimeOut(true);
|
||||
+ threadPoolExecutor.prestartAllCoreThreads();
|
||||
+ // Leaf end - Ability to use Virtual Thread for async scheduler
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: etil2jz <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Tue, 2 Aug 2022 14:48:12 +0200
|
||||
Subject: [PATCH] Mirai: Configurable chat message signatures
|
||||
|
||||
Fixed & Updated by Dreeam-qwq
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/Dreeam-qwq/Mirai
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/etil2jz/Mirai
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
index 7cb9622b88d9ef1ae5cae00485bb9995c87e206f..aeccb214872d47e4730abb84e78100ffe98d55ff 100644
|
||||
--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
|
||||
@@ -317,7 +317,7 @@ public final class ChatProcessor {
|
||||
|
||||
private void sendToServer(final ChatType.Bound chatType, final @Nullable Function<Audience, net.minecraft.network.chat.Component> msgFunction) {
|
||||
final PlayerChatMessage toConsoleMessage = msgFunction == null ? ChatProcessor.this.message : ChatProcessor.this.message.withUnsignedContent(msgFunction.apply(ChatProcessor.this.server.console));
|
||||
- ChatProcessor.this.server.logChatMessage(toConsoleMessage.decoratedContent(), chatType, !org.galemc.gale.configuration.GaleGlobalConfiguration.get().logToConsole.chat.notSecureMarker || ChatProcessor.this.server.getPlayerList().verifyChatTrusted(toConsoleMessage) ? null : "Not Secure"); // Gale - do not log Not Secure marker
|
||||
+ ChatProcessor.this.server.logChatMessage(toConsoleMessage.decoratedContent(), chatType, !org.dreeam.leaf.config.modules.network.ChatMessageSignature.enabled || !org.galemc.gale.configuration.GaleGlobalConfiguration.get().logToConsole.chat.notSecureMarker || ChatProcessor.this.server.getPlayerList().verifyChatTrusted(toConsoleMessage) ? null : "Not Secure"); // Gale - do not log Not Secure marker // Leaf - Mirai - Configurable chat message signatures
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Apehum <apehumchik@gmail.com>
|
||||
Date: Thu, 9 Dec 2021 02:18:17 +0800
|
||||
Subject: [PATCH] Matter: Secure Seed
|
||||
|
||||
TODO - Dreeam:
|
||||
Able to write feature seed in existed level.dat (Done)
|
||||
Update to BLAKE3
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/plasmoapp/matter
|
||||
|
||||
Co-authored-by: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
index c855f1f6f70000b03594ce50553147d9821b796b..91f680bb9905319d9ce2b3fe2746bdb8e968aba9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
@@ -196,7 +196,14 @@ public class CraftChunk implements Chunk {
|
||||
@Override
|
||||
public boolean isSlimeChunk() {
|
||||
// 987234911L is taken from Slime when seeing if a slime can spawn in a chunk
|
||||
- return this.level.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), level.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ if (this.level.paperConfig().entities.spawning.allChunksAreSlimeChunks) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ return org.dreeam.leaf.config.modules.misc.SecureSeed.enabled
|
||||
+ ? level.getChunk(this.getX(), this.getZ()).isSlimeChunk()
|
||||
+ : WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), level.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper;
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 540c84579ef57ec73bc5250ff889139ddcdf296b..1c3382da80fa3e08b130d48c135c4100580b70f6 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1354,7 +1354,11 @@ public final class CraftServer implements Server {
|
||||
registryAccess = levelDataAndDimensions.dimensions().dimensionsRegistryAccess();
|
||||
} else {
|
||||
LevelSettings levelSettings;
|
||||
- WorldOptions worldOptions = new WorldOptions(creator.seed(), creator.generateStructures(), false);
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldOptions worldOptions = org.dreeam.leaf.config.modules.misc.SecureSeed.enabled
|
||||
+ ? new WorldOptions(creator.seed(), su.plo.matter.Globals.createRandomWorldSeed(), creator.generateStructures(), false)
|
||||
+ : new WorldOptions(creator.seed(), creator.generateStructures(), false);
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
WorldDimensions worldDimensions;
|
||||
|
||||
DedicatedServerProperties.WorldDimensionData properties = new DedicatedServerProperties.WorldDimensionData(GsonHelper.parse((creator.generatorSettings().isEmpty()) ? "{}" : creator.generatorSettings()), creator.type().name().toLowerCase(Locale.ROOT));
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
Date: Tue, 9 Nov 2077 00:00:00 +0800
|
||||
Subject: [PATCH] Faster random generator
|
||||
|
||||
This patch replaces LegacyRandomSource with FasterRandomSource by default,
|
||||
which is faster in general.
|
||||
|
||||
Benchmark results (10,000,000 iterations) (Azul Zulu 23.0.1)
|
||||
|
||||
FasterRandomSource (Leaf) (Backed by Xoroshiro128PlusPlus): 51,633,700 ns
|
||||
LegacyRandomSource (Vanilla): 254,857,500 ns
|
||||
ThreadUnsafeRandom (Moonrise): 102,265,100 ns
|
||||
SimpleThreadUnsafeRandom (Moonrise): 97,054,600 ns
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
index 73c51c66857f53128b737304205295b67e8444e8..348bf5ed91ded3537a86bc0708e0158ad4f9296d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
|
||||
@@ -97,7 +97,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
||||
}
|
||||
|
||||
private static WorldgenRandom getSeededRandom() {
|
||||
- return new WorldgenRandom(new LegacyRandomSource(0));
|
||||
+ return new WorldgenRandom(org.dreeam.leaf.config.modules.opt.FastRNG.worldgenEnabled() ? new org.dreeam.leaf.util.math.random.FasterRandomSource(0) : new LegacyRandomSource(0)); // Leaf - Faster random generator
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Wed, 7 Aug 2024 18:54:01 +0800
|
||||
Subject: [PATCH] Configurable unknown command message
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 7c585b71d06f438f414227c2625f27b6c323045e..de271fc2a9866d60ec760b9589faef260de1cb67 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -151,7 +151,6 @@ public class SpigotConfig {
|
||||
}
|
||||
|
||||
public static String whitelistMessage;
|
||||
- public static String unknownCommandMessage;
|
||||
public static String serverFullMessage;
|
||||
public static String outdatedClientMessage = "Outdated client! Please use {0}";
|
||||
public static String outdatedServerMessage = "Outdated server! I'm still on {0}";
|
||||
@@ -167,7 +166,6 @@ public class SpigotConfig {
|
||||
}
|
||||
|
||||
SpigotConfig.whitelistMessage = SpigotConfig.transform(SpigotConfig.getString("messages.whitelist", "You are not whitelisted on this server!"));
|
||||
- SpigotConfig.unknownCommandMessage = SpigotConfig.transform(SpigotConfig.getString("messages.unknown-command", "Unknown command. Type \"/help\" for help."));
|
||||
SpigotConfig.serverFullMessage = SpigotConfig.transform(SpigotConfig.getString("messages.server-full", "The server is full!"));
|
||||
SpigotConfig.outdatedClientMessage = SpigotConfig.transform(SpigotConfig.getString("messages.outdated-client", SpigotConfig.outdatedClientMessage));
|
||||
SpigotConfig.outdatedServerMessage = SpigotConfig.transform(SpigotConfig.getString("messages.outdated-server", SpigotConfig.outdatedServerMessage));
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Taiyou06 <kaandindar21@gmail.com>
|
||||
Date: Sun, 10 Nov 2024 14:36:18 +0100
|
||||
Subject: [PATCH] Replace world map with optimized collection
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 1c3382da80fa3e08b130d48c135c4100580b70f6..ffdea8befa77ec655b1df929715fcbdc60d6a966 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -281,7 +281,7 @@ public final class CraftServer implements Server {
|
||||
private final StructureManager structureManager;
|
||||
final DedicatedServer console;
|
||||
private final DedicatedPlayerList playerList;
|
||||
- private final Map<String, World> worlds = new LinkedHashMap<>();
|
||||
+ private final Map<String, World> worlds = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Leaf - Replace world map with optimized collection
|
||||
private final it.unimi.dsi.fastutil.objects.Object2ObjectMap<UUID, World> worldsByUUID = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Gale - MultiPaper - CraftBukkit UUID to world map
|
||||
private YamlConfiguration configuration;
|
||||
private YamlConfiguration commandsConfiguration;
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Sun, 28 Jul 2024 17:44:10 +0800
|
||||
Subject: [PATCH] Cache CraftEntityType#minecraftToBukkit convert
|
||||
|
||||
The minecraftToBukkit EntityType convert call is expensive in mob spawn. This convert call is ued for spawn event call,
|
||||
and the results are always same, thus there is no need to do the convert process every time, just cache it.
|
||||
Save ~0.16ms per tick, and improve 11660ms -> 60ms in around 1 hour.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
index 47db4546242974a40f7fc1e34f237fd1f06d5f37..8ffc90b579338d3cf26046ecb497438ac7d02370 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityType.java
|
||||
@@ -15,14 +15,26 @@ import org.bukkit.entity.EntityType;
|
||||
|
||||
public class CraftEntityType {
|
||||
|
||||
+ private static final java.util.Map<net.minecraft.world.entity.EntityType<?>, EntityType> MINECRAFT_TO_BUKKIT_KEY_CACHE = new java.util.concurrent.ConcurrentHashMap<>(); // Leaf - Cache CraftEntityType#minecraftToBukkit convert
|
||||
+
|
||||
public static EntityType minecraftToBukkit(net.minecraft.world.entity.EntityType<?> minecraft) {
|
||||
Preconditions.checkArgument(minecraft != null);
|
||||
|
||||
+ // Leaf start - Cache CraftEntityType#minecraftToBukkit convert
|
||||
+ EntityType asBukkit = MINECRAFT_TO_BUKKIT_KEY_CACHE.get(minecraft);
|
||||
+
|
||||
+ if (org.dreeam.leaf.config.modules.opt.EnableCachedMTBEntityTypeConvert.enabled && asBukkit != null) {
|
||||
+ return asBukkit;
|
||||
+ }
|
||||
+ // Leaf end - Cache CraftEntityType#minecraftToBukkit convert
|
||||
+
|
||||
net.minecraft.core.Registry<net.minecraft.world.entity.EntityType<?>> registry = CraftRegistry.getMinecraftRegistry(Registries.ENTITY_TYPE);
|
||||
EntityType bukkit = Registry.ENTITY_TYPE.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location()));
|
||||
|
||||
Preconditions.checkArgument(bukkit != null);
|
||||
|
||||
+ MINECRAFT_TO_BUKKIT_KEY_CACHE.put(minecraft, bukkit); // Leaf - Cache CraftEntityType#minecraftToBukkit convert
|
||||
+
|
||||
return bukkit;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
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/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 083cc48abea81560b34c30653e766d650a2d3850..7d22c1ee7fa98fc2d04d353fe19387ca3334f52a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -1741,6 +1741,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);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
Date: Wed, 23 Oct 2024 23:54:00 +0800
|
||||
Subject: [PATCH] Asynchronous locator
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/thebrightspark/AsyncLocator
|
||||
|
||||
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
index 69cdd304d255d52c9b7dc9b6a33ffdb630b79abe..a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1 100644
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
@@ -105,6 +105,12 @@ public class TickThread extends Thread {
|
||||
this(null, run, name);
|
||||
}
|
||||
|
||||
+ // Leaf start - Asynchronous locator
|
||||
+ public TickThread(final Runnable run, final String name, final int id) {
|
||||
+ this(null, run, name, id);
|
||||
+ }
|
||||
+ // Leaf end - Asynchronous locator
|
||||
+
|
||||
public TickThread(final ThreadGroup group, final Runnable run, final String name) {
|
||||
this(group, run, name, ID_GENERATOR.incrementAndGet());
|
||||
}
|
||||
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 84905d7802f8a5c3f68e15f1b17ef08216ad1f4e..196fddeab452e7bc89ef6758635e1d07074e7416 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
@@ -48,6 +48,12 @@ class PaperEventManager {
|
||||
return;
|
||||
}
|
||||
// Leaf end - Multithreaded tracker
|
||||
+ // Leaf start - Asynchronous locator
|
||||
+ if (org.dreeam.leaf.config.modules.async.AsyncLocator.enabled) {
|
||||
+ net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(event::callEvent);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaf end - Asynchronous locator
|
||||
throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 28 Jun 2018 22:13:44 -0400
|
||||
Subject: [PATCH] EMC: Don't use snapshots for acquiring blockstate
|
||||
|
||||
Original license: MIT
|
||||
Original project: https://github.com/starlis/empirecraft
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index 4a709355acab59c5ded1ffdc321be3252482bd0b..c8f0b24fd9336259e42c4746061793e156978ad3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -333,7 +333,7 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public BlockState getState() {
|
||||
- return CraftBlockStates.getBlockState(this);
|
||||
+ return CraftBlockStates.getBlockState(this, org.dreeam.leaf.config.modules.opt.TileEntitySnapshotCreation.enabled); // Leaf - EMC - Don't use snapshots for acquiring blockstate
|
||||
}
|
||||
|
||||
// Paper start
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
index 5da891112402b758ca618967c4662027efbe14dc..23d0c901c1261de30748654b34a7ce6c51ad9c24 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
@@ -186,7 +186,7 @@ public final class CraftBlockStates {
|
||||
}
|
||||
|
||||
public static BlockState getBlockState(Block block) {
|
||||
- return CraftBlockStates.getBlockState(block, true);
|
||||
+ return CraftBlockStates.getBlockState(block, org.dreeam.leaf.config.modules.opt.TileEntitySnapshotCreation.enabled); // Leaf - EMC - Don't use snapshots for acquiring blockstate
|
||||
}
|
||||
|
||||
public static BlockState getBlockState(Block block, boolean useSnapshot) {
|
||||
@@ -0,0 +1,22 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
Date: Tue, 9 Nov 2077 00:00:00 +0800
|
||||
Subject: [PATCH] Faster CraftServer#getworlds list creation
|
||||
|
||||
CraftServer#getWorlds/Bukkit#getWorlds is frequently used in plugins,
|
||||
replacing ArrayList with Fastutil ObjectArrayList
|
||||
brings about 40% performance improvement in benchmark.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index ffdea8befa77ec655b1df929715fcbdc60d6a966..028a30ae3c9dd411e70b1bc8ac42067c06d0335f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -954,7 +954,7 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public List<World> getWorlds() {
|
||||
- return new ArrayList<World>(this.worlds.values());
|
||||
+ return new it.unimi.dsi.fastutil.objects.ObjectArrayList<World>(this.worlds.values()); // Leaf - Faster CraftServer#getWorlds list creation
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Sat, 2 Nov 2024 04:15:20 -0400
|
||||
Subject: [PATCH] Cache chunk key
|
||||
|
||||
Cache convert process between ChunkPos < - > chunkKey
|
||||
This patch didn't cahce SectionPos or BlockPos to chunkKey, since it needs to consider the mutable blockpos siutation.
|
||||
|
||||
TODO: Cache block pos and section pos, whether need?
|
||||
|
||||
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java
|
||||
index 036c1a287db04c0191e5f84b027ea68d31447cbc..3cda726b5ef7419da512889d3edd1fb6935e6a54 100644
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java
|
||||
@@ -20,7 +20,7 @@ public final class CoordinateUtils {
|
||||
}
|
||||
|
||||
public static long getChunkKey(final ChunkPos pos) {
|
||||
- return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL);
|
||||
+ return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL); // Leaf - Cache chunk key
|
||||
}
|
||||
|
||||
public static long getChunkKey(final SectionPos pos) {
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
Date: Mon, 1 Nov 2077 00:00:00 +0800
|
||||
Subject: [PATCH] Async structure locate api
|
||||
|
||||
This patch depends on Asynchronous locator patch.
|
||||
|
||||
Added some asynchronous structure locate methods in World,
|
||||
requires async-locator to be enabled in Leaf config, or else it will fall back to sync methods.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index a76797c08cb5912d0525fa21217d45b61b110259..2538a0de7fd6b1026fff51e5d066c5b0811b7cda 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -2272,6 +2272,45 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
return new CraftStructureSearchResult(CraftStructure.minecraftToBukkit(found.getSecond().value()), CraftLocation.toBukkit(found.getFirst(), this));
|
||||
}
|
||||
|
||||
+ // Leaf start - Async structure locate api
|
||||
+ @Override
|
||||
+ public void locateNearestStructureAsync(Location origin, StructureType structureType, int radius, boolean findUnexplored, Consumer<StructureSearchResult> afterComplete) {
|
||||
+ List<Structure> structures = new ArrayList<>();
|
||||
+ for (Structure structure : RegistryAccess.registryAccess().getRegistry(RegistryKey.STRUCTURE)) {
|
||||
+ if (structure.getStructureType() == structureType) {
|
||||
+ structures.add(structure);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.locateNearestStructureAsync(origin, structures, radius, findUnexplored, afterComplete);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void locateNearestStructureAsync(Location origin, Structure structure, int radius, boolean findUnexplored, Consumer<StructureSearchResult> afterComplete) {
|
||||
+ this.locateNearestStructureAsync(origin, List.of(structure), radius, findUnexplored, afterComplete);
|
||||
+ }
|
||||
+
|
||||
+ public void locateNearestStructureAsync(Location origin, List<Structure> structures, int radius, boolean findUnexplored, Consumer<@Nullable StructureSearchResult> afterComplete) {
|
||||
+ if (!org.dreeam.leaf.config.modules.async.AsyncLocator.enabled) afterComplete.accept(locateNearestStructure(origin, structures, radius, findUnexplored));
|
||||
+ BlockPos originPos = BlockPos.containing(origin.getX(), origin.getY(), origin.getZ());
|
||||
+ List<Holder<net.minecraft.world.level.levelgen.structure.Structure>> holders = new ArrayList<>();
|
||||
+
|
||||
+ for (Structure structure : structures) {
|
||||
+ holders.add(Holder.direct(CraftStructure.bukkitToMinecraft(structure)));
|
||||
+ }
|
||||
+
|
||||
+ org.dreeam.leaf.async.locate.AsyncLocator.locate(
|
||||
+ this.getHandle(), HolderSet.direct(holders), originPos, radius, findUnexplored
|
||||
+ ).thenOnServerThread(found -> {
|
||||
+ if (found == null) {
|
||||
+ afterComplete.accept(null);
|
||||
+ return;
|
||||
+ }
|
||||
+ afterComplete.accept(new CraftStructureSearchResult(CraftStructure.minecraftToBukkit(found.getSecond().value()), CraftLocation.toBukkit(found.getFirst(), this)));
|
||||
+ });
|
||||
+ }
|
||||
+ // Leaf end - Async structure locate api
|
||||
+
|
||||
// Paper start
|
||||
@Override
|
||||
public double getCoordinateScale() {
|
||||
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
Date: Wed, 19 Feb 2025 00:36:20 -0500
|
||||
Subject: [PATCH] PlayerInventoryOverflowEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index f850e6cea92edc87ed54cf54488b5ebb606913ed..b5af3cc6865408ffef40f4868970cff947834afc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -340,6 +340,15 @@ public class CraftInventory implements Inventory {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaf start - PlayerInventoryOverflowEvent
|
||||
+ if (org.dreeam.leaf.event.player.PlayerInventoryOverflowEvent.getHandlerList().getRegisteredListeners().length > 0 && !leftover.isEmpty() && this.getHolder() instanceof org.bukkit.craftbukkit.entity.CraftPlayer craftPlayer) {
|
||||
+ new org.dreeam.leaf.event.player.PlayerInventoryOverflowEvent(craftPlayer, leftover).callEvent();
|
||||
+
|
||||
+ leftover = new HashMap<>();
|
||||
+ }
|
||||
+ // Leaf end - PlayerInventoryOverflowEvent
|
||||
+
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,688 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Altiami <yoshimo.kristin@gmail.com>
|
||||
Date: Wed, 5 Mar 2025 13:16:44 -0800
|
||||
Subject: [PATCH] SparklyPaper: Parallel world ticking
|
||||
|
||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||
|
||||
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
index a4aa2615823d77920ff55b8aa0bcc27a54b8c3e1..2fb65ce228da94eb7d9364ee0f94582300178f1d 100644
|
||||
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
|
||||
@@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class TickThread extends Thread {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class);
|
||||
+ private static final boolean HARD_THROW = !org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.disableHardThrow; // SparklyPaper - parallel world ticking - THIS SHOULD NOT BE DISABLED SINCE IT CAN CAUSE DATA CORRUPTION!!! Anyhow, for production servers, if you want to make a test run to see if the server could crash, you can test it with this disabled
|
||||
|
||||
private static String getThreadContext() {
|
||||
return "thread=" + Thread.currentThread().getName();
|
||||
@@ -26,14 +27,14 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final String reason) {
|
||||
if (!isTickThread()) {
|
||||
LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable());
|
||||
- throw new IllegalStateException(reason);
|
||||
+ if (HARD_THROW) throw new IllegalStateException(reason); // SparklyPaper - parallel world ticking
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) {
|
||||
if (!isTickThreadFor(world, pos)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos;
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -42,7 +43,7 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) {
|
||||
if (!isTickThreadFor(world, pos, blockRadius)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius;
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -51,7 +52,7 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) {
|
||||
if (!isTickThreadFor(world, pos)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos;
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -60,7 +61,7 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) {
|
||||
if (!isTickThreadFor(world, chunkX, chunkZ)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ);
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ) + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -69,7 +70,7 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Entity entity, final String reason) {
|
||||
if (!isTickThreadFor(entity)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity);
|
||||
+ reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity) + " - " + getTickThreadInformation(entity.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -78,7 +79,7 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Level world, final AABB aabb, final String reason) {
|
||||
if (!isTickThreadFor(world, aabb)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb;
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
@@ -87,12 +88,70 @@ public class TickThread extends Thread {
|
||||
public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) {
|
||||
if (!isTickThreadFor(world, blockX, blockZ)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ);
|
||||
+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ) + " - " + getTickThreadInformation(world.getServer()); // SparklyPaper - parallel world ticking
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information
|
||||
+ // Because we only tick worlds in parallel (instead of regions), we can use this for our checks
|
||||
+ public static void ensureTickThread(final net.minecraft.server.level.ServerLevel world, final String reason) {
|
||||
+ if (!isTickThreadFor(world)) {
|
||||
+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); // SparklyPaper - parallel world ticking
|
||||
+ if (HARD_THROW) throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // This is an additional method to check if it is a tick thread but ONLY a tick thread
|
||||
+ public static void ensureOnlyTickThread(final String reason) {
|
||||
+ boolean isTickThread = isTickThread();
|
||||
+ boolean isServerLevelTickThread = isServerLevelTickThread();
|
||||
+ if (!isTickThread || isServerLevelTickThread) {
|
||||
+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread ONLY tick thread check: " + reason, new Throwable());
|
||||
+ if (HARD_THROW) throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // This is an additional method to check if the tick thread is bound to a specific world or if it is an async thread.
|
||||
+ public static void ensureTickThreadOrAsyncThread(final net.minecraft.server.level.ServerLevel world, final String reason) {
|
||||
+ boolean isValidTickThread = isTickThreadFor(world);
|
||||
+ boolean isAsyncThread = !isTickThread();
|
||||
+ boolean isValid = isAsyncThread || isValidTickThread;
|
||||
+ if (!isValid) {
|
||||
+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread or async thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable());
|
||||
+ if (HARD_THROW) throw new IllegalStateException(reason);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static String getTickThreadInformation(net.minecraft.server.MinecraftServer minecraftServer) {
|
||||
+ StringBuilder sb = new StringBuilder();
|
||||
+ Thread currentThread = Thread.currentThread();
|
||||
+ sb.append("Is tick thread? ");
|
||||
+ sb.append(currentThread instanceof TickThread);
|
||||
+ sb.append("; Is server level tick thread? ");
|
||||
+ sb.append(currentThread instanceof ServerLevelTickThread);
|
||||
+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) {
|
||||
+ sb.append("; Currently ticking level: ");
|
||||
+ if (serverLevelTickThread.currentlyTickingServerLevel != null) {
|
||||
+ sb.append(serverLevelTickThread.currentlyTickingServerLevel.getWorld().getName());
|
||||
+ } else {
|
||||
+ sb.append("null");
|
||||
+ }
|
||||
+ }
|
||||
+ sb.append("; Is iterating over levels? ");
|
||||
+ sb.append(minecraftServer.isIteratingOverLevels);
|
||||
+ sb.append("; Are we going to hard throw? ");
|
||||
+ sb.append(HARD_THROW);
|
||||
+ return sb.toString();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isServerLevelTickThread() {
|
||||
+ return Thread.currentThread() instanceof ServerLevelTickThread;
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
+
|
||||
public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */
|
||||
|
||||
private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
|
||||
@@ -133,46 +192,74 @@ public class TickThread extends Thread {
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final BlockPos pos) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final BlockPos pos, final int blockRadius) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (add missing replacement / use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final ChunkPos pos) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final Vec3 pos) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final AABB aabb) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final double blockX, final double blockZ) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final Vec3 position, final Vec3 deltaMovement, final int buffer) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final int fromChunkX, final int fromChunkZ, final int toChunkX, final int toChunkZ) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ, final int radius) {
|
||||
- return isTickThread();
|
||||
+ return isTickThreadFor(world); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
+ }
|
||||
+
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information
|
||||
+ // Because we only tick worlds in parallel (instead of regions), we can use this for our checks
|
||||
+ public static boolean isTickThreadFor(final Level world) {
|
||||
+ if (Thread.currentThread() instanceof ServerLevelTickThread serverLevelTickThread) {
|
||||
+ return serverLevelTickThread.currentlyTickingServerLevel == world;
|
||||
+ } else {
|
||||
+ return isTickThread();
|
||||
+ }
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Entity entity) {
|
||||
- return isTickThread();
|
||||
+ if (entity == null) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return isTickThreadFor(entity.level()); // Leaf - SparklyPaper - parallel world ticking mod (use methods for what they were made for)
|
||||
+ }
|
||||
+
|
||||
+ public static class ServerLevelTickThread extends TickThread {
|
||||
+ public ServerLevelTickThread(String name) {
|
||||
+ super(name);
|
||||
+ }
|
||||
+
|
||||
+ public ServerLevelTickThread(Runnable run, String name) {
|
||||
+ super(run, name);
|
||||
+ }
|
||||
+
|
||||
+ public net.minecraft.server.level.ServerLevel currentlyTickingServerLevel;
|
||||
}
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
}
|
||||
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 196fddeab452e7bc89ef6758635e1d07074e7416..55a2ffa0fff6ef66b9bd5069300c09e9e3535c0d 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
@@ -28,6 +28,7 @@ import java.util.logging.Level;
|
||||
class PaperEventManager {
|
||||
|
||||
private final Server server;
|
||||
+ private final org.purpurmc.purpur.util.MinecraftInternalPlugin minecraftInternalPlugin = new org.purpurmc.purpur.util.MinecraftInternalPlugin(); // Leaf - Parallel world ticking
|
||||
|
||||
public PaperEventManager(Server server) {
|
||||
this.server = server;
|
||||
@@ -40,6 +41,12 @@ class PaperEventManager {
|
||||
if (listeners.length == 0) return;
|
||||
// Leaf end - Skip event if no listeners
|
||||
if (event.isAsynchronous() && this.server.isPrimaryThread()) {
|
||||
+ // Leaf start - Parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.runAsyncTasksSync) {
|
||||
+ org.bukkit.Bukkit.getAsyncScheduler().runNow(minecraftInternalPlugin, task -> event.callEvent());
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaf end - Parallel world ticking
|
||||
throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously.");
|
||||
} else if (!event.isAsynchronous() && !this.server.isPrimaryThread() && !this.server.isStopping()) {
|
||||
// Leaf start - Multithreaded tracker
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 2538a0de7fd6b1026fff51e5d066c5b0811b7cda..c114dfd419177cf45f02617acde86ea4abcbdc96 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -456,7 +456,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
|
||||
private boolean unloadChunk0(int x, int z, boolean save) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
|
||||
+ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
+ else
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
|
||||
+ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
if (!this.isChunkLoaded(x, z)) {
|
||||
return true;
|
||||
}
|
||||
@@ -473,6 +478,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean refreshChunk(int x, int z) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
|
||||
if (playerChunk == null) return false;
|
||||
|
||||
@@ -523,7 +530,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(int x, int z, boolean generate) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
|
||||
+ // Leaf start - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
+ else
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
|
||||
+ // Leaf end - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
warnUnsafeChunk("loading a faraway chunk", x, z); // Paper
|
||||
ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper
|
||||
|
||||
@@ -751,6 +763,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
this.world.captureTreeGeneration = true;
|
||||
this.world.captureBlockStates = true;
|
||||
boolean grownTree = this.generateTree(loc, type);
|
||||
@@ -866,6 +880,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer<net.minecraft.world.level.ServerExplosion> configurator) {
|
||||
// Paper end - expand explosion API
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
net.minecraft.world.level.Level.ExplosionInteraction explosionType;
|
||||
if (!breakBlocks) {
|
||||
explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks
|
||||
@@ -957,6 +973,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper
|
||||
// Transient load for this tick
|
||||
return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z);
|
||||
@@ -987,6 +1005,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, Holder<net.minecraft.world.level.biome.Biome> bb) {
|
||||
BlockPos pos = new BlockPos(x, 0, z);
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
if (this.world.hasChunkAt(pos)) {
|
||||
net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos);
|
||||
|
||||
@@ -2329,6 +2349,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs)
|
||||
getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position));
|
||||
}
|
||||
// Paper end
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index c8f0b24fd9336259e42c4746061793e156978ad3..2b2d1819b0d953800c1757ad7c92de4f781efa0d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -76,6 +76,11 @@ public class CraftBlock implements Block {
|
||||
}
|
||||
|
||||
public net.minecraft.world.level.block.state.BlockState getNMS() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
return this.world.getBlockState(this.position);
|
||||
}
|
||||
|
||||
@@ -156,6 +161,11 @@ public class CraftBlock implements Block {
|
||||
}
|
||||
|
||||
private void setData(final byte data, int flags) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flags);
|
||||
}
|
||||
|
||||
@@ -197,6 +207,11 @@ public class CraftBlock implements Block {
|
||||
}
|
||||
|
||||
public static boolean setBlockState(LevelAccessor world, BlockPos pos, net.minecraft.world.level.block.state.BlockState oldState, net.minecraft.world.level.block.state.BlockState newState, boolean applyPhysics) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
// SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in block entity cleanup
|
||||
if (oldState.hasBlockEntity() && newState.getBlock() != oldState.getBlock()) { // SPIGOT-3725 remove old block entity if block changes
|
||||
// SPIGOT-4612: faster - just clear tile
|
||||
@@ -345,18 +360,33 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public Biome getBiome() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ());
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@Override
|
||||
public Biome getComputedBiome() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
return this.getWorld().getComputedBiome(this.getX(), this.getY(), this.getZ());
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
public void setBiome(Biome bio) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio);
|
||||
}
|
||||
|
||||
@@ -377,6 +407,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public boolean isBlockIndirectlyPowered() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
return this.world.getMinecraftWorld().hasNeighborSignal(this.position);
|
||||
}
|
||||
|
||||
@@ -416,6 +451,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public int getBlockPower(BlockFace face) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
int power = 0;
|
||||
net.minecraft.world.level.Level world = this.world.getMinecraftWorld();
|
||||
int x = this.getX();
|
||||
@@ -484,6 +524,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public boolean breakNaturally() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
return this.breakNaturally(null);
|
||||
}
|
||||
|
||||
@@ -543,6 +588,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public boolean applyBoneMeal(BlockFace face) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
Direction direction = CraftBlock.blockFaceToNotch(face);
|
||||
BlockFertilizeEvent event = null;
|
||||
ServerLevel world = this.getCraftWorld().getHandle();
|
||||
@@ -554,8 +604,8 @@ public class CraftBlock implements Block {
|
||||
world.captureTreeGeneration = false;
|
||||
|
||||
if (!world.capturedBlockStates.isEmpty()) {
|
||||
- TreeType treeType = SaplingBlock.treeType;
|
||||
- SaplingBlock.treeType = null;
|
||||
+ TreeType treeType = SaplingBlock.getTreeTypeRT(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
||||
+ SaplingBlock.setTreeTypeRT(null); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
||||
List<BlockState> states = new ArrayList<>(world.capturedBlockStates.values());
|
||||
world.capturedBlockStates.clear();
|
||||
StructureGrowEvent structureEvent = null;
|
||||
@@ -645,6 +695,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
Preconditions.checkArgument(start != null, "Location start cannot be null");
|
||||
Preconditions.checkArgument(this.getWorld().equals(start.getWorld()), "Location start cannot be a different world");
|
||||
start.checkFinite();
|
||||
@@ -686,6 +741,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public boolean canPlace(BlockData data) {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
Preconditions.checkArgument(data != null, "BlockData cannot be null");
|
||||
net.minecraft.world.level.block.state.BlockState iblockdata = ((CraftBlockData) data).getState();
|
||||
net.minecraft.world.level.Level world = this.world.getMinecraftWorld();
|
||||
@@ -720,6 +780,11 @@ public class CraftBlock implements Block {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && world instanceof ServerLevel serverWorld) { // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
final ServerLevel level = this.world.getMinecraftWorld();
|
||||
this.getNMS().tick(level, this.position, level.random);
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockEntityState.java
|
||||
index 7d3a4669ccd6fbfaf8716dc19c538c6ba17a5ffe..72311b765908e0f155d2b8fb7a066fe893d8ae73 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockEntityState.java
|
||||
@@ -26,6 +26,27 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
|
||||
private final T snapshot;
|
||||
public boolean snapshotDisabled; // Paper
|
||||
public static boolean DISABLE_SNAPSHOT = false; // Paper
|
||||
+ public static ThreadLocal<Boolean> DISABLE_SNAPSHOT_TL = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (distinguish name)
|
||||
+
|
||||
+ // Leaf start - SparklyPaper - parallel world ticking mod
|
||||
+ // refer to original field in case plugins attempt to modify it
|
||||
+ public static boolean getDisableSnapshotTL() {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && DISABLE_SNAPSHOT_TL.get())
|
||||
+ return true;
|
||||
+ synchronized (CraftBlockEntityState.class) {
|
||||
+ return DISABLE_SNAPSHOT;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // update original field in case plugins attempt to access it
|
||||
+ public static void setDisableSnapshotTL(boolean value) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled)
|
||||
+ DISABLE_SNAPSHOT_TL.set(value);
|
||||
+ synchronized (CraftBlockEntityState.class) {
|
||||
+ DISABLE_SNAPSHOT = value;
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end - SparklyPaper - parallel world ticking mod
|
||||
|
||||
public CraftBlockEntityState(World world, T blockEntity) {
|
||||
super(world, blockEntity.getBlockPos(), blockEntity.getBlockState());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockState.java
|
||||
index 647c1edd3338ce4f80e48ea769ed381cd158758d..07cf2e9412da5d307a7ca5edc202f8286e5ae25a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockState.java
|
||||
@@ -219,6 +219,12 @@ public class CraftBlockState implements BlockState {
|
||||
LevelAccessor access = this.getWorldHandle();
|
||||
CraftBlock block = this.getBlock();
|
||||
|
||||
+ // SparklyPaper start - parallel world ticking
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && access instanceof net.minecraft.server.level.ServerLevel serverWorld) {
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously");
|
||||
+ }
|
||||
+ // SparklyPaper end - parallel world ticking
|
||||
+
|
||||
if (block.getType() != this.getType()) {
|
||||
if (!force) {
|
||||
return false;
|
||||
@@ -367,6 +373,8 @@ public class CraftBlockState implements BlockState {
|
||||
|
||||
@Override
|
||||
public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) // Leaf - SparklyPaper - parallel world ticking mod (make configurable)
|
||||
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); // SparklyPaper - parallel world ticking
|
||||
this.requirePlaced();
|
||||
net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item);
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
index 23d0c901c1261de30748654b34a7ce6c51ad9c24..ca5edb79379ee74cb66e6eb7f63fe725a689170a 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/state/CraftBlockStates.java
|
||||
@@ -196,14 +196,14 @@ public final class CraftBlockStates {
|
||||
BlockPos pos = craftBlock.getPosition();
|
||||
net.minecraft.world.level.block.state.BlockState state = craftBlock.getNMS();
|
||||
BlockEntity blockEntity = craftBlock.getHandle().getBlockEntity(pos);
|
||||
- boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
|
||||
- CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
|
||||
+ boolean prev = CraftBlockEntityState.getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
||||
+ CraftBlockEntityState.setDisableSnapshotTL(!useSnapshot); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
||||
try {
|
||||
CraftBlockState blockState = CraftBlockStates.getBlockState(world, pos, state, blockEntity);
|
||||
blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access
|
||||
return blockState;
|
||||
} finally {
|
||||
- CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
|
||||
+ CraftBlockEntityState.setDisableSnapshotTL(prev); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 7d22c1ee7fa98fc2d04d353fe19387ca3334f52a..cfe328104a57410204504721f1d8840f4819344b 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -809,6 +809,28 @@ public class CraftEventFactory {
|
||||
}
|
||||
|
||||
public static BlockPos sourceBlockOverride = null; // SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPos up to five methods deep.
|
||||
+ public static final ThreadLocal<BlockPos> sourceBlockOverrideRT = new ThreadLocal<>(); // SparklyPaper - parallel world ticking (this is from Folia, fixes concurrency bugs with sculk catalysts)
|
||||
+
|
||||
+ // Leaf start - SparklyPaper - parallel world ticking mod
|
||||
+ // refer to original field in case plugins attempt to modify it
|
||||
+ public static BlockPos getSourceBlockOverrideRT() {
|
||||
+ BlockPos sourceBlockOverrideRTCopy;
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled && (sourceBlockOverrideRTCopy = sourceBlockOverrideRT.get()) != null)
|
||||
+ return sourceBlockOverrideRTCopy;
|
||||
+ synchronized (CraftEventFactory.class) {
|
||||
+ return sourceBlockOverride;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // update original field in case plugins attempt to access it
|
||||
+ public static void setSourceBlockOverrideRT(BlockPos value) {
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled)
|
||||
+ sourceBlockOverrideRT.set(value);
|
||||
+ synchronized (CraftEventFactory.class) {
|
||||
+ sourceBlockOverride = value;
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end - SparklyPaper - parallel world ticking mod
|
||||
|
||||
public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState state, int flags) {
|
||||
return handleBlockSpreadEvent(world, source, target, state, flags, false);
|
||||
@@ -824,7 +846,10 @@ public class CraftEventFactory {
|
||||
CraftBlockState snapshot = CraftBlockStates.getBlockState(world, target);
|
||||
snapshot.setData(state);
|
||||
|
||||
- BlockSpreadEvent event = new BlockSpreadEvent(snapshot.getBlock(), CraftBlock.at(world, CraftEventFactory.sourceBlockOverride != null ? CraftEventFactory.sourceBlockOverride : source), snapshot);
|
||||
+ // Leaf start - SparklyPaper parallel world ticking mod (collapse original behavior)
|
||||
+ final BlockPos sourceBlockOverrideRTSnap = getSourceBlockOverrideRT();
|
||||
+ BlockSpreadEvent event = new BlockSpreadEvent(snapshot.getBlock(), CraftBlock.at(world, sourceBlockOverrideRTSnap != null ? sourceBlockOverrideRTSnap : source), snapshot); // SparklyPaper - parallel world ticking
|
||||
+ // Leaf end - SparklyPaper parallel world ticking mod (collapse original behavior)
|
||||
if (event.callEvent()) {
|
||||
boolean result = snapshot.place(flags);
|
||||
return !checkSetResult || result;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
index e4e2e42d0ca25df7fe9f2dd4275610e45fcb2c84..e7c6b2ab5f2c68f3319ccd52785c8d3488a2eef7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
@@ -19,11 +19,39 @@ class CraftAsyncTask extends CraftTask {
|
||||
|
||||
@Override
|
||||
public boolean isSync() {
|
||||
+ // Leaf start - Parallel world ticking
|
||||
+ // Return true if we should run this task synchronously when parallel world ticking is enabled and runAsyncTasksSync is true
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled &&
|
||||
+ org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.runAsyncTasksSync) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Leaf end - Parallel world ticking
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
+ // Leaf start - Parallel world ticking
|
||||
+ // If parallel world ticking is enabled and we're configured to run async tasks sync,
|
||||
+ // execute the task as if it were a sync task (directly on the main thread)
|
||||
+ if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled &&
|
||||
+ org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.runAsyncTasksSync) {
|
||||
+ try {
|
||||
+ super.run();
|
||||
+ } catch (final Throwable t) {
|
||||
+ this.getOwner().getLogger().log(
|
||||
+ Level.WARNING,
|
||||
+ String.format(
|
||||
+ "Plugin %s generated an exception while executing task %s (forced sync mode)",
|
||||
+ this.getOwner().getDescription().getFullName(),
|
||||
+ this.getTaskId()),
|
||||
+ t);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaf end - Parallel world ticking
|
||||
+
|
||||
+ // Original async implementation
|
||||
final Thread thread = Thread.currentThread();
|
||||
// Paper start - name threads according to running plugin
|
||||
final String nameBefore = thread.getName();
|
||||
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: froobynooby <froobynooby@froobworld.com>
|
||||
Date: Wed, 17 Jul 2024 18:46:11 +0930
|
||||
Subject: [PATCH] Paper PR: Throttle failed spawn attempts
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/PaperMC/Paper
|
||||
Paper pull request: https://github.com/PaperMC/Paper/pull/11099
|
||||
|
||||
For example config in paper-world-defaults.yml
|
||||
```
|
||||
spawning-throttle:
|
||||
failed-attempts-threshold: 1200
|
||||
throttled-ticks-per-spawn:
|
||||
ambient: 10 # default value in bukkit.yml tickers-per * 10
|
||||
axolotls: 10
|
||||
creature: 4000
|
||||
monster: 10
|
||||
underground_water_creature: 10
|
||||
water_ambient: 10
|
||||
water_creature: 10
|
||||
```
|
||||
|
||||
This patch adds the option to use longer ticks-per-spawn for a given
|
||||
mob type in chunks where spawn attempts are consecutively failing.
|
||||
|
||||
This behaviour is particularly useful on servers where players build
|
||||
mob farms. Mob farm designs often require making surrounding chunks
|
||||
spawnproof, which causes the server to waste CPU cycles trying to spawn mobs in
|
||||
vain. Throttling spawn attempts in suspected spawnproof chunks improves
|
||||
performance without noticeably advantaging or disadvantaging the mob farm.
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
||||
index 9511f978f6c7da506f67928f5a5a92ecf28e5930..6c298304f842612d0e063b578f274eed04b32960 100644
|
||||
--- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
||||
+++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
|
||||
@@ -182,6 +182,17 @@ public class WorldConfiguration extends ConfigurationPart {
|
||||
@MergeMap
|
||||
public Reference2IntMap<MobCategory> ticksPerSpawn = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1)));
|
||||
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ public SpawningThrottle spawningThrottle;
|
||||
+
|
||||
+ public class SpawningThrottle extends ConfigurationPart {
|
||||
+ public IntOr.Disabled failedAttemptsThreshold = IntOr.Disabled.DISABLED;
|
||||
+
|
||||
+ @MergeMap
|
||||
+ public Reference2IntMap<MobCategory> throttledTicksPerSpawn = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1)));
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
+
|
||||
@ConfigSerializable
|
||||
public record DespawnRangePair(@Required DespawnRange hard, @Required DespawnRange soft) {
|
||||
public static DespawnRangePair createDefault() {
|
||||
Reference in New Issue
Block a user