mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-23 17:09:29 +00:00
Merge branch 'ver/1.21.4' into dev/1.21.5
This commit is contained in:
@@ -17,6 +17,7 @@ public net.minecraft.world.entity.decoration.ArmorStand noTickEquipmentDirty
|
|||||||
public net.minecraft.world.entity.monster.Shulker MAX_SCALE
|
public net.minecraft.world.entity.monster.Shulker MAX_SCALE
|
||||||
public net.minecraft.world.entity.player.Player canGlide()Z
|
public net.minecraft.world.entity.player.Player canGlide()Z
|
||||||
public net.minecraft.world.item.CrossbowItem getShotPitch(Lnet/minecraft/util/RandomSource;I)F
|
public net.minecraft.world.item.CrossbowItem getShotPitch(Lnet/minecraft/util/RandomSource;I)F
|
||||||
|
public net.minecraft.world.level.block.PoweredRailBlock findPoweredRailSignal(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;ZI)Z
|
||||||
public net.minecraft.world.level.block.entity.FuelValues values
|
public net.minecraft.world.level.block.entity.FuelValues values
|
||||||
public net.minecraft.world.level.chunk.PaletteResize
|
public net.minecraft.world.level.chunk.PaletteResize
|
||||||
public net.minecraft.world.level.chunk.storage.RegionFile getOversizedData(II)Lnet/minecraft/nbt/CompoundTag;
|
public net.minecraft.world.level.chunk.storage.RegionFile getOversizedData(II)Lnet/minecraft/nbt/CompoundTag;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ subprojects {
|
|||||||
options.release = 21
|
options.release = 21
|
||||||
options.isFork = true
|
options.isFork = true
|
||||||
options.compilerArgs.addAll(listOf("-Xlint:-deprecation", "-Xlint:-removal"))
|
options.compilerArgs.addAll(listOf("-Xlint:-deprecation", "-Xlint:-removal"))
|
||||||
options.forkOptions.memoryMaximumSize = "6g" // Prevent OOM during building
|
options.forkOptions.memoryMaximumSize = "2g" // Prevent OOM during building
|
||||||
}
|
}
|
||||||
tasks.withType<Javadoc> {
|
tasks.withType<Javadoc> {
|
||||||
options.encoding = Charsets.UTF_8.name()
|
options.encoding = Charsets.UTF_8.name()
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||||
|
Date: Wed, 31 Jul 2024 22:05:21 +0800
|
||||||
|
Subject: [PATCH] Leaf Bootstrap
|
||||||
|
|
||||||
|
Removed since Leaf 1.21.4, useless
|
||||||
|
|
||||||
|
org.bukkit.craftbukkit.Main#main -> LeafBootstrap -> PaperBootstrap -> ...
|
||||||
|
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||||
|
index ecb0fcd1f3b3f3d7751eded3cdf0977c1889c9ed..d0becb56a9911ef4cc55ae8d7c47832f442ad52f 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||||
|
@@ -278,7 +278,8 @@ public class Main {
|
||||||
|
System.setProperty("jdk.console", "java.base"); // Paper - revert default console provider back to java.base so we can have our own jline
|
||||||
|
//System.out.println("Loading libraries, please wait...");
|
||||||
|
//net.minecraft.server.Main.main(options);
|
||||||
|
- io.papermc.paper.PaperBootstrap.boot(options);
|
||||||
|
+ //io.papermc.paper.PaperBootstrap.boot(options); // Leaf - Leaf Boostrap - diff on change
|
||||||
|
+ org.dreeam.leaf.LeafBootstrap.boot(options); // Leaf - Leaf Boostrap
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ Date: Thu, 1 Aug 2024 00:43:05 +0900
|
|||||||
Subject: [PATCH] ShreddedPaper: Don't block main thread in
|
Subject: [PATCH] ShreddedPaper: Don't block main thread in
|
||||||
Connection#syncAfterConfigurationChange
|
Connection#syncAfterConfigurationChange
|
||||||
|
|
||||||
|
Removed since Leaf 1.21.4, replaced by async config switch
|
||||||
|
|
||||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||||
index 00a82873d226f113278632a53c0faca420dd67d4..5b46036868b6c9d082e35591e58735e16adaae62 100644
|
index 00a82873d226f113278632a53c0faca420dd67d4..5b46036868b6c9d082e35591e58735e16adaae62 100644
|
||||||
@@ -3,6 +3,8 @@ From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|||||||
Date: Thu, 5 Sep 2024 15:42:15 -0700
|
Date: Thu, 5 Sep 2024 15:42:15 -0700
|
||||||
Subject: [PATCH] Moonrise: Optimise checkInsideBlocks
|
Subject: [PATCH] Moonrise: Optimise checkInsideBlocks
|
||||||
|
|
||||||
|
Removed since Leaf 1.21.3, Optimized in Minecraft
|
||||||
|
|
||||||
Original license: GPLv3
|
Original license: GPLv3
|
||||||
Original project: https://github.com/Tuinity/Moonrise
|
Original project: https://github.com/Tuinity/Moonrise
|
||||||
|
|
||||||
@@ -3,6 +3,8 @@ From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|||||||
Date: Thu, 5 Sep 2024 16:23:04 -0700
|
Date: Thu, 5 Sep 2024 16:23:04 -0700
|
||||||
Subject: [PATCH] Moonrise: Avoid streams for block retrieval in Entity#move
|
Subject: [PATCH] Moonrise: Avoid streams for block retrieval in Entity#move
|
||||||
|
|
||||||
|
Removed since Leaf 1.21.3, Optimized in Minecraft
|
||||||
|
|
||||||
Original license: GPLv3
|
Original license: GPLv3
|
||||||
Original project: https://github.com/Tuinity/Moonrise
|
Original project: https://github.com/Tuinity/Moonrise
|
||||||
|
|
||||||
@@ -3,6 +3,7 @@ From: Taiyou06 <kaandindar21@gmail.com>
|
|||||||
Date: Fri, 8 Nov 2024 00:54:42 +0100
|
Date: Fri, 8 Nov 2024 00:54:42 +0100
|
||||||
Subject: [PATCH] Use MCUtil.asyncExecutor for MAIN_WORKER_EXECUTOR
|
Subject: [PATCH] Use MCUtil.asyncExecutor for MAIN_WORKER_EXECUTOR
|
||||||
|
|
||||||
|
Removed since Leaf 1.21.3
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||||
index 815253d03b85a7a476c1efdeca9496fd64afc137..bb4c9bbebaefe9a0c7d213e9b2b07308e684dc7c 100644
|
index 815253d03b85a7a476c1efdeca9496fd64afc137..bb4c9bbebaefe9a0c7d213e9b2b07308e684dc7c 100644
|
||||||
@@ -105,7 +105,7 @@ index dddbb18992348fb7e8a6552423d134809cd7fdbc..0e6e71030e3fd1335fff796b861524a4
|
|||||||
if (this.hidesOnlinePlayers()) {
|
if (this.hidesOnlinePlayers()) {
|
||||||
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||||
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
||||||
index 792ba93b531e9586e26aafa00830022a8996fc04..e4ea26ae84efde7ce54e08a246a6ea2ae2a17151 100644
|
index abccabb8a0a1a9730b7df070dd25f3ca215af362..0a4bcc4c44fed2ededafaf0641315e072b7ba771 100644
|
||||||
--- a/net/minecraft/server/PlayerAdvancements.java
|
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||||
@@ -168,6 +168,11 @@ public class PlayerAdvancements {
|
@@ -168,6 +168,11 @@ public class PlayerAdvancements {
|
||||||
@@ -134,7 +134,7 @@ index 5c0a04db38821dbb0cba2bb6f0787f113d167efd..cd153db93f709c3142942fac88ae3ca2
|
|||||||
.filter(player -> !playerList.isOp(player.getGameProfile()))
|
.filter(player -> !playerList.isOp(player.getGameProfile()))
|
||||||
.map(player -> player.getGameProfile().getName()),
|
.map(player -> player.getGameProfile().getName()),
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 94ee31a4a02edb003b98a09b0311355c1db4f547..f8bd39ddd7b6948734254acfb8b0235eff774133 100644
|
index b49dd636e730f0c5b609df68ee51bcd12efc1eaa..5e971bca365c692d4ce0c58693592002ce01471c 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -216,6 +216,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -216,6 +216,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -153,7 +153,7 @@ index 94ee31a4a02edb003b98a09b0311355c1db4f547..f8bd39ddd7b6948734254acfb8b0235e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Paper start
|
// Paper start
|
||||||
@@ -2672,6 +2674,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2698,6 +2700,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
||||||
if (entity instanceof ServerPlayer serverPlayer) {
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
ServerLevel.this.players.add(serverPlayer);
|
ServerLevel.this.players.add(serverPlayer);
|
||||||
@@ -165,7 +165,7 @@ index 94ee31a4a02edb003b98a09b0311355c1db4f547..f8bd39ddd7b6948734254acfb8b0235e
|
|||||||
ServerLevel.this.updateSleepingPlayerList();
|
ServerLevel.this.updateSleepingPlayerList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2742,6 +2749,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2768,6 +2775,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||||
if (entity instanceof ServerPlayer serverPlayer) {
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
ServerLevel.this.players.remove(serverPlayer);
|
ServerLevel.this.players.remove(serverPlayer);
|
||||||
@@ -178,7 +178,7 @@ index 94ee31a4a02edb003b98a09b0311355c1db4f547..f8bd39ddd7b6948734254acfb8b0235e
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||||
index 622257dbbe572de33e15abef9055016268730261..dfb4524d80f642eff1b146dd2fbfa07f21d844c6 100644
|
index d44c3baa2ef30d5cd4c46e491ff9198fa558513c..f89d28595fa9ca12e414f7b3cc86085ff0769e72 100644
|
||||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||||
@@ -195,7 +195,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
@@ -195,7 +195,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||||
@@ -191,7 +191,7 @@ index 622257dbbe572de33e15abef9055016268730261..dfb4524d80f642eff1b146dd2fbfa07f
|
|||||||
private final ServerStatsCounter stats;
|
private final ServerStatsCounter stats;
|
||||||
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
||||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
index e3d09d5f4efb32bb276e001e5ee747a775b502ee..78b15d750d75e5d4c2318a3a18e83afdd5f4fbe1 100644
|
index c26bf04abe86b566e7f5cd29191a0a853f9808f8..4c172e2aee3e48d42009cd39b28f694aa71e20e3 100644
|
||||||
--- a/net/minecraft/server/players/PlayerList.java
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
+++ b/net/minecraft/server/players/PlayerList.java
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
@@ -132,6 +132,7 @@ public abstract class PlayerList {
|
@@ -132,6 +132,7 @@ public abstract class PlayerList {
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ index 5ab2c8333178335515e619b87ae420f948c83bd1..be3b2f023897a8823560ee059cb16ec9
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index c50a301a0c2365c2052aefc6a23fcf6fa82e1b9d..ac751d460ae0c8dbb858c4047c459a11b57ae175 100644
|
index c50a301a0c2365c2052aefc6a23fcf6fa82e1b9d..7f791ff5bdf6c29c78f863d21af16270a74d8e7e 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -291,6 +291,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -291,6 +291,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
@@ -326,7 +326,20 @@ index c50a301a0c2365c2052aefc6a23fcf6fa82e1b9d..ac751d460ae0c8dbb858c4047c459a11
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1677,6 +1690,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -923,6 +936,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
}
|
||||||
|
|
||||||
|
serverLevel.save(null, flush, serverLevel.noSave && !forced, close); // Paper - add close param
|
||||||
|
+ // Leaf start - SparklyPaper - parallel world ticking - Shutdown handling for async reads
|
||||||
|
+ // Only prepare shutdown if 'close' is true, indicating this save is part of server shutdown
|
||||||
|
+ if (close && org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) {
|
||||||
|
+ serverLevel.prepareShutdown();
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - SparklyPaper - parallel world ticking - Shutdown handling for async reads
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1677,6 +1696,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +358,7 @@ index c50a301a0c2365c2052aefc6a23fcf6fa82e1b9d..ac751d460ae0c8dbb858c4047c459a11
|
|||||||
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
||||||
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
||||||
this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
||||||
@@ -1743,28 +1768,50 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1743,28 +1774,50 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isIteratingOverLevels = true; // Paper - Throw exception on world create while being ticked
|
this.isIteratingOverLevels = true; // Paper - Throw exception on world create while being ticked
|
||||||
@@ -414,7 +427,7 @@ index c50a301a0c2365c2052aefc6a23fcf6fa82e1b9d..ac751d460ae0c8dbb858c4047c459a11
|
|||||||
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
|
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
|
||||||
|
|
||||||
this.tickConnection();
|
this.tickConnection();
|
||||||
@@ -1844,6 +1891,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1844,6 +1897,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
||||||
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
||||||
newLevels.remove(level.dimension());
|
newLevels.remove(level.dimension());
|
||||||
@@ -568,7 +581,7 @@ index d4048661575ebfaf128ba25da365843774364e0e..33dd16a26edd2974f04d9a868d3e58e8
|
|||||||
|
|
||||||
// Gale start - Pufferfish - SIMD support
|
// Gale start - Pufferfish - SIMD support
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index a66e5f6652d9633c856490de36d8d8fdf8a5298a..60e0296312030d25f917c568c17ce86d08e18122 100644
|
index a66e5f6652d9633c856490de36d8d8fdf8a5298a..d6524d5c442555eaeb4d90f6a101262ee669f0d9 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -182,7 +182,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -182,7 +182,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -580,23 +593,173 @@ index a66e5f6652d9633c856490de36d8d8fdf8a5298a..60e0296312030d25f917c568c17ce86d
|
|||||||
// Paper - rewrite chunk system
|
// Paper - rewrite chunk system
|
||||||
private final GameEventDispatcher gameEventDispatcher;
|
private final GameEventDispatcher gameEventDispatcher;
|
||||||
public boolean noSave;
|
public boolean noSave;
|
||||||
@@ -208,6 +208,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -208,7 +208,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
private double preciseTime; // Purpur - Configurable daylight cycle
|
private double preciseTime; // Purpur - Configurable daylight cycle
|
||||||
private boolean forceTime; // Purpur - Configurable daylight cycle
|
private boolean forceTime; // Purpur - Configurable daylight cycle
|
||||||
private final RandomSequences randomSequences;
|
private final RandomSequences randomSequences;
|
||||||
|
-
|
||||||
+ public java.util.concurrent.ExecutorService tickExecutor; // SparklyPaper - parallel world ticking
|
+ public java.util.concurrent.ExecutorService tickExecutor; // SparklyPaper - parallel world ticking
|
||||||
|
+ public final java.util.concurrent.ConcurrentLinkedQueue<org.dreeam.leaf.async.world.WorldReadRequest> asyncReadRequestQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Leaf - SparklyPaper - parallel world ticking
|
||||||
|
+ private volatile boolean isShuttingDown = false; // Leaf - SparklyPaper - parallel world ticking - Shutdown handling for async reads
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
|
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
|
||||||
@@ -703,6 +704,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
public final UUID uuid;
|
||||||
|
@@ -703,8 +705,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||||
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
||||||
this.realPlayers = Lists.newArrayList(); // Leaves - skip
|
this.realPlayers = Lists.newArrayList(); // Leaves - skip
|
||||||
+ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.dreeam.leaf.async.world.SparklyPaperServerLevelTickExecutorThreadFactory(getWorld().getName())); // SparklyPaper - parallel world ticking
|
+ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.dreeam.leaf.async.world.SparklyPaperServerLevelTickExecutorThreadFactory(getWorld().getName())); // SparklyPaper - parallel world ticking
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Leaf start - SparklyPaper - parallel world ticking - Shutdown handling for async reads
|
||||||
|
+ public boolean isShuttingDown() {
|
||||||
|
+ return this.isShuttingDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ public void prepareShutdown() {
|
||||||
|
+ this.isShuttingDown = true;
|
||||||
|
+ org.dreeam.leaf.async.world.WorldReadRequest req;
|
||||||
|
+ int clearedRequests = 0;
|
||||||
|
+ while ((req = this.asyncReadRequestQueue.poll()) != null) {
|
||||||
|
+ req.future().completeExceptionally(new IllegalStateException("World " + this.getWorld().getName() + " is shutting down. Cannot process buffered read: " + req.type()));
|
||||||
|
+ clearedRequests++;
|
||||||
|
+ }
|
||||||
|
+ if (clearedRequests > 0) MinecraftServer.LOGGER.info("PWT: Cleared " + clearedRequests + " pending async read requests for world " + this.getWorld().getName() + " during shutdown.");
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - SparklyPaper - parallel world ticking - Shutdown handling for async reads
|
||||||
|
+
|
||||||
// Paper start
|
// Paper start
|
||||||
@@ -1313,9 +1315,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@Override
|
||||||
|
public boolean hasChunk(int chunkX, int chunkZ) {
|
||||||
|
@@ -737,8 +757,112 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
|
||||||
|
public Player[] eligibleDespawnCheckingPlayerCache = new Player[0]; // Leaf - Cache eligible players for despawn checks
|
||||||
|
|
||||||
|
+ // Leaf start - SparklyPaper - parallel world ticking
|
||||||
|
+ private void processAsyncReadRequests() {
|
||||||
|
+ // Only process if parallel ticking is enabled and buffering is active
|
||||||
|
+ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled ||
|
||||||
|
+ !org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.asyncUnsafeReadHandling.equals("BUFFERED")) {
|
||||||
|
+ // Clear queue if buffering gets disabled to prevent memory leaks
|
||||||
|
+ if (!this.asyncReadRequestQueue.isEmpty()) {
|
||||||
|
+ org.dreeam.leaf.async.world.WorldReadRequest req;
|
||||||
|
+ while ((req = this.asyncReadRequestQueue.poll()) != null) {
|
||||||
|
+ req.future().completeExceptionally(new IllegalStateException("Async read buffering disabled while request was pending."));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ org.dreeam.leaf.async.world.WorldReadRequest request;
|
||||||
|
+ int processed = 0;
|
||||||
|
+ // Limit processing per tick to avoid stalling the tick loop
|
||||||
|
+ int maxToProcess = 16384; // Consider making this configurable
|
||||||
|
+
|
||||||
|
+ while (processed < maxToProcess && (request = this.asyncReadRequestQueue.poll()) != null) {
|
||||||
|
+ processed++;
|
||||||
|
+ // Ensure we are on the correct thread before executing
|
||||||
|
+ // This check might be redundant if called correctly from tick(), but good for safety
|
||||||
|
+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Processing async read request off-thread");
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ Object result = executeReadRequest(request);
|
||||||
|
+ request.future().complete(result);
|
||||||
|
+ } catch (Throwable t) {
|
||||||
|
+ // Log the error from the tick thread side
|
||||||
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Exception processing buffered async world read for type " + request.type(), t);
|
||||||
|
+ request.future().completeExceptionally(t);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Executes the actual read operation based on the request type
|
||||||
|
+ private Object executeReadRequest(org.dreeam.leaf.async.world.WorldReadRequest request) {
|
||||||
|
+ Object[] params = request.params();
|
||||||
|
+ BlockPos pos; // Declare pos outside the switch
|
||||||
|
+
|
||||||
|
+ switch (request.type()) {
|
||||||
|
+ case BLOCK_GET_NMS_STATE: { //
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ return this.getBlockState(pos);
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_GET_BIOME: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ return this.getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_GET_COMPUTED_BIOME: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ return this.getBiome(pos);
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_IS_INDIRECTLY_POWERED: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ return this.hasNeighborSignal(pos);
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_GET_BLOCK_POWER: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ org.bukkit.block.BlockFace face = (org.bukkit.block.BlockFace) params[1];
|
||||||
|
+ int power = 0;
|
||||||
|
+ Direction notchDir = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(face);
|
||||||
|
+
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.DOWN || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.below(), Direction.DOWN)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.below()));
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.UP || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.above(), Direction.UP)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.above()));
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.EAST || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.east(), Direction.EAST)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.east()));
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.WEST || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.west(), Direction.WEST)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.west()));
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.NORTH || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.north(), Direction.NORTH)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.north()));
|
||||||
|
+ if ((face == org.bukkit.block.BlockFace.SOUTH || face == org.bukkit.block.BlockFace.SELF) && this.hasSignal(pos.south(), Direction.SOUTH)) power = org.bukkit.craftbukkit.block.CraftBlock.getPower(power, this.getBlockState(pos.south()));
|
||||||
|
+
|
||||||
|
+ boolean indirectlyPowered = (face == org.bukkit.block.BlockFace.SELF) ? this.hasNeighborSignal(pos) : (this.getSignal(pos, notchDir) > 0); // Simplified indirect check for faces
|
||||||
|
+ return power > 0 ? power : (indirectlyPowered ? 15 : 0);
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_RAY_TRACE: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ org.bukkit.Location start = (org.bukkit.Location) params[1];
|
||||||
|
+ org.bukkit.util.Vector direction = (org.bukkit.util.Vector) params[2];
|
||||||
|
+ double maxDistance = (double) params[3];
|
||||||
|
+ org.bukkit.FluidCollisionMode fluidCollisionMode = (org.bukkit.FluidCollisionMode) params[4];
|
||||||
|
+
|
||||||
|
+ org.bukkit.util.Vector dir = direction.clone().normalize().multiply(maxDistance);
|
||||||
|
+ Vec3 startPos = org.bukkit.craftbukkit.util.CraftLocation.toVec3D(start);
|
||||||
|
+ Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
|
||||||
|
+
|
||||||
|
+ return this.clip(new net.minecraft.world.level.ClipContext(startPos, endPos, net.minecraft.world.level.ClipContext.Block.OUTLINE, org.bukkit.craftbukkit.CraftFluidCollisionMode.toNMS(fluidCollisionMode), net.minecraft.world.phys.shapes.CollisionContext.empty()), pos); // Pass block pos
|
||||||
|
+ }
|
||||||
|
+ case BLOCK_CAN_PLACE: {
|
||||||
|
+ pos = (BlockPos) params[0];
|
||||||
|
+ org.bukkit.block.data.BlockData data = (org.bukkit.block.data.BlockData) params[1];
|
||||||
|
+ net.minecraft.world.level.block.state.BlockState nmsData = ((org.bukkit.craftbukkit.block.data.CraftBlockData) data).getState();
|
||||||
|
+ return nmsData.canSurvive(this, pos);
|
||||||
|
+ }
|
||||||
|
+ // Add cases for other ReadOperationType values here...
|
||||||
|
+ // case GET_ENTITIES_IN_BOX: ... (complex, needs careful list handling)
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ throw new UnsupportedOperationException("Unsupported buffered read type: " + request.type());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - SparklyPaper - parallel world ticking
|
||||||
|
+
|
||||||
|
public void tick(BooleanSupplier hasTimeLeft) {
|
||||||
|
this.handlingTick = true;
|
||||||
|
+ this.processAsyncReadRequests(); // Leaf - SparklyPaper - parallel world ticking
|
||||||
|
TickRateManager tickRateManager = this.tickRateManager();
|
||||||
|
boolean runsNormally = tickRateManager.runsNormally();
|
||||||
|
if (runsNormally) {
|
||||||
|
@@ -746,6 +870,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
this.advanceWeatherCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaf start - SparklyPaper - parallel world ticking
|
||||||
|
+ if (!org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) {
|
||||||
|
+ this.moonrise$midTickTasks();
|
||||||
|
+ } else if ((++this.tickedBlocksOrFluids & 7L) != 0L) { // Keep original mid-tick logic for PWT enabled
|
||||||
|
+ this.server.moonrise$executeMidTickTasks();
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - SparklyPaper - parallel world ticking
|
||||||
|
+
|
||||||
|
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
|
||||||
|
if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) { // Purpur - Config for skipping night
|
||||||
|
// Paper start - create time skip event - move up calculations
|
||||||
|
@@ -1313,9 +1445,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
fluidState.tick(this, pos, blockState);
|
fluidState.tick(this, pos, blockState);
|
||||||
}
|
}
|
||||||
// Paper start - rewrite chunk system
|
// Paper start - rewrite chunk system
|
||||||
@@ -611,7 +774,7 @@ index a66e5f6652d9633c856490de36d8d8fdf8a5298a..60e0296312030d25f917c568c17ce86d
|
|||||||
// Paper end - rewrite chunk system
|
// Paper end - rewrite chunk system
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1326,9 +1331,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1326,9 +1461,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
blockState.tick(this, pos, this.random);
|
blockState.tick(this, pos, this.random);
|
||||||
}
|
}
|
||||||
// Paper start - rewrite chunk system
|
// Paper start - rewrite chunk system
|
||||||
@@ -626,7 +789,7 @@ index a66e5f6652d9633c856490de36d8d8fdf8a5298a..60e0296312030d25f917c568c17ce86d
|
|||||||
// Paper end - rewrite chunk system
|
// Paper end - rewrite chunk system
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1579,6 +1587,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1579,6 +1717,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPlayer(ServerPlayer player) {
|
private void addPlayer(ServerPlayer player) {
|
||||||
@@ -635,7 +798,7 @@ index a66e5f6652d9633c856490de36d8d8fdf8a5298a..60e0296312030d25f917c568c17ce86d
|
|||||||
Entity entity = this.getEntities().get(player.getUUID());
|
Entity entity = this.getEntities().get(player.getUUID());
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID());
|
LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID());
|
||||||
@@ -1591,7 +1601,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1591,7 +1731,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ Subject: [PATCH] SparklyPaper: Track each world MSPT
|
|||||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index ac751d460ae0c8dbb858c4047c459a11b57ae175..24926aa7ed5c78b235659daf18b224b14beb744c 100644
|
index 7f791ff5bdf6c29c78f863d21af16270a74d8e7e..1431a0fac3c8a846535c1bd2f60a1279d08f14ea 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -1693,7 +1693,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1699,7 +1699,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
// Leaf start - SparklyPaper - parallel world ticking mod (move level ticking logic out for branch convergence)
|
// Leaf start - SparklyPaper - parallel world ticking mod (move level ticking logic out for branch convergence)
|
||||||
private void tickLevel(ServerLevel serverLevel, BooleanSupplier hasTimeLeft) {
|
private void tickLevel(ServerLevel serverLevel, BooleanSupplier hasTimeLeft) {
|
||||||
try {
|
try {
|
||||||
@@ -27,10 +27,10 @@ index ac751d460ae0c8dbb858c4047c459a11b57ae175..24926aa7ed5c78b235659daf18b224b1
|
|||||||
CrashReport crashReport = CrashReport.forThrowable(levelTickingException, "Exception ticking world");
|
CrashReport crashReport = CrashReport.forThrowable(levelTickingException, "Exception ticking world");
|
||||||
serverLevel.fillReportDetails(crashReport);
|
serverLevel.fillReportDetails(crashReport);
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 31abf2da10bc9b4b7825ed4b3d4e9da52feb2e39..9ba1c29b75ba0eb545097eef4fe568c53ebd885c 100644
|
index d6524d5c442555eaeb4d90f6a101262ee669f0d9..5c1f99a8fd9920b30e6a80769bc306591510012a 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -573,6 +573,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -574,6 +574,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
}
|
}
|
||||||
// Paper end - chunk tick iteration
|
// Paper end - chunk tick iteration
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ Original project: https://github.com/LeavesMC/Leaves
|
|||||||
Commit: 41476d86922416c45f703df2871890831fc42bb5
|
Commit: 41476d86922416c45f703df2871890831fc42bb5
|
||||||
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
index aa6f0588f282e3152ef9639d6fb2b8cd1d54bdb7..514c2d414ac59c71929a7686204465c72d122513 100644
|
index ddf9a5d3af7ebe8e5c69d7dcb8a1c3a28d8178e3..3fabeaa91832eacc103416682aec3ce6121858fb 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
@@ -508,6 +508,7 @@ public final class CraftServer implements Server {
|
@@ -509,6 +509,7 @@ public final class CraftServer implements Server {
|
||||||
this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
|
this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
|
||||||
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
||||||
this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark
|
this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark
|
||||||
@@ -23,7 +23,7 @@ index aa6f0588f282e3152ef9639d6fb2b8cd1d54bdb7..514c2d414ac59c71929a7686204465c7
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean getCommandBlockOverride(String command) {
|
public boolean getCommandBlockOverride(String command) {
|
||||||
@@ -1140,6 +1141,7 @@ public final class CraftServer implements Server {
|
@@ -1141,6 +1142,7 @@ public final class CraftServer implements Server {
|
||||||
org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur - Purpur config files
|
org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur - Purpur config files
|
||||||
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
||||||
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
||||||
@@ -27,10 +27,10 @@ index 4c003acccdd2dd17918b15316001e52e7670123e..780f3a48152fef6a06dc67bf7fbd1965
|
|||||||
HandlerList handlers = event.getHandlers();
|
HandlerList handlers = event.getHandlers();
|
||||||
RegisteredListener[] listeners = handlers.getRegisteredListeners();
|
RegisteredListener[] listeners = handlers.getRegisteredListeners();
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
index eec03c52172b8250c18318094093c752da97dbe6..f57e12a72cabe279a6a465f4397b44621a2d5cb0 100644
|
index 3fabeaa91832eacc103416682aec3ce6121858fb..7ca77be262e6c8c9882db42295a42487b672d43e 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
@@ -322,6 +322,8 @@ public final class CraftServer implements Server {
|
@@ -323,6 +323,8 @@ public final class CraftServer implements Server {
|
||||||
private final io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler asyncScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler();
|
private final io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler asyncScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler();
|
||||||
private final io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler globalRegionScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler();
|
private final io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler globalRegionScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler();
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ index eec03c52172b8250c18318094093c752da97dbe6..f57e12a72cabe279a6a465f4397b4462
|
|||||||
@Override
|
@Override
|
||||||
public final io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler() {
|
public final io.papermc.paper.threadedregions.scheduler.RegionScheduler getRegionScheduler() {
|
||||||
return this.regionizedScheduler;
|
return this.regionizedScheduler;
|
||||||
@@ -410,7 +412,7 @@ public final class CraftServer implements Server {
|
@@ -411,7 +413,7 @@ public final class CraftServer implements Server {
|
||||||
public CraftServer(DedicatedServer console, PlayerList playerList) {
|
public CraftServer(DedicatedServer console, PlayerList playerList) {
|
||||||
this.console = console;
|
this.console = console;
|
||||||
this.playerList = (DedicatedPlayerList) playerList;
|
this.playerList = (DedicatedPlayerList) playerList;
|
||||||
@@ -48,7 +48,7 @@ index eec03c52172b8250c18318094093c752da97dbe6..f57e12a72cabe279a6a465f4397b4462
|
|||||||
@Override
|
@Override
|
||||||
public CraftPlayer apply(ServerPlayer player) {
|
public CraftPlayer apply(ServerPlayer player) {
|
||||||
return player.getBukkitEntity();
|
return player.getBukkitEntity();
|
||||||
@@ -3456,4 +3458,11 @@ public final class CraftServer implements Server {
|
@@ -3461,4 +3463,11 @@ public final class CraftServer implements Server {
|
||||||
return getServer().lagging;
|
return getServer().lagging;
|
||||||
}
|
}
|
||||||
// Purpur end - Lagging threshold
|
// Purpur end - Lagging threshold
|
||||||
@@ -74,10 +74,10 @@ index 8635cd772c5c2ae0ba326812ff2a1a179285a86f..cc024874fbde9678bdddfdca7c250808
|
|||||||
if (entity instanceof EnderDragonPart complexPart) {
|
if (entity instanceof EnderDragonPart complexPart) {
|
||||||
if (complexPart.parentMob instanceof EnderDragon) {
|
if (complexPart.parentMob instanceof EnderDragon) {
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
index 2f027c504859f7ef41ef243bbc16535c6595ec28..abc762829bc0447936ab9e06eabcb42419578585 100644
|
index 9d733dd366d54b0780746a6235d81dc17607cad2..7bd58d683ca2534d36510590e0895dce7c46551a 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
@@ -2281,7 +2281,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
@@ -2280,7 +2280,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canSee(Player player) {
|
public boolean canSee(Player player) {
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,703 +0,0 @@
|
|||||||
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 548fcd9646dee0c40b6ba9b3dafb9ca157dfe324..d7af94890bfccd6ff665d920cecfa1e5be626aa4 100644
|
|
||||||
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
|
||||||
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
|
||||||
@@ -40,6 +40,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.dreeam.leaf.async.world.PWTEventScheduler.getScheduler().scheduleTask(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 af33cab59932f4ec135caf94dc5828930833daf6..92463ddc6fdcf542ce4a6d2a5059d4a9f7a6085a 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
@@ -455,7 +455,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;
|
|
||||||
}
|
|
||||||
@@ -472,6 +477,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;
|
|
||||||
|
|
||||||
@@ -522,7 +529,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
|
|
||||||
|
|
||||||
@@ -750,6 +762,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);
|
|
||||||
@@ -865,6 +879,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
|
|
||||||
@@ -956,6 +972,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);
|
|
||||||
@@ -986,6 +1004,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);
|
|
||||||
|
|
||||||
@@ -2328,6 +2348,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 811823a1a7e24a19a7e37eb4c08efdfa19e839ed..b94efcab12d41fa8745e5bb55cfa6481d8262e74 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
|
||||||
@@ -75,6 +75,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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -157,6 +162,11 @@ public class CraftBlock implements Block {
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setData(final byte data, int flag) {
|
|
||||||
+ // 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), flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -198,6 +208,12 @@ public class CraftBlock implements Block {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, 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 tile entity cleanup
|
|
||||||
if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes
|
|
||||||
// SPIGOT-4612: faster - just clear tile
|
|
||||||
@@ -343,18 +359,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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -375,6 +406,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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -414,6 +450,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 +525,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 +589,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 +605,8 @@ public class CraftBlock implements Block {
|
|
||||||
world.captureTreeGeneration = false;
|
|
||||||
|
|
||||||
if (world.capturedBlockStates.size() > 0) {
|
|
||||||
- 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> blocks = new ArrayList<>(world.capturedBlockStates.values());
|
|
||||||
world.capturedBlockStates.clear();
|
|
||||||
StructureGrowEvent structureEvent = null;
|
|
||||||
@@ -644,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();
|
|
||||||
@@ -685,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();
|
|
||||||
@@ -719,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/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
|
||||||
index 768d3f93da2522d467183654260a8bd8653588b1..5cef786fa2e5dfd3e7b79918bc73af02891b0bea 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/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 tileEntity) {
|
|
||||||
super(world, tileEntity.getBlockPos(), tileEntity.getBlockState());
|
|
||||||
@@ -34,8 +55,8 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
|
|
||||||
|
|
||||||
try { // Paper - Show blockstate location if we failed to read it
|
|
||||||
// Paper start
|
|
||||||
- this.snapshotDisabled = DISABLE_SNAPSHOT;
|
|
||||||
- if (DISABLE_SNAPSHOT) {
|
|
||||||
+ this.snapshotDisabled = getDisableSnapshotTL(); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
|
||||||
+ if (this.snapshotDisabled) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
|
||||||
this.snapshot = this.tileEntity;
|
|
||||||
} else {
|
|
||||||
this.snapshot = this.createSnapshot(tileEntity);
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
|
||||||
index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..d106f65e4b745242484a195958fc559268a7dee0 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
|
|
||||||
@@ -215,6 +215,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;
|
|
||||||
@@ -350,6 +356,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/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
|
||||||
index 55572e799b5c8a74a546ac8febc14f80d5731c52..08a06c23c831a4de45b3e537228b837911019da8 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
|
||||||
@@ -249,8 +249,8 @@ public final class CraftBlockStates {
|
|
||||||
net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS();
|
|
||||||
BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition);
|
|
||||||
// Paper start - block state snapshots
|
|
||||||
- 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 {
|
|
||||||
// Paper end
|
|
||||||
CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity);
|
|
||||||
@@ -258,7 +258,7 @@ public final class CraftBlockStates {
|
|
||||||
return blockState;
|
|
||||||
// Paper start
|
|
||||||
} finally {
|
|
||||||
- CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
|
|
||||||
+ CraftBlockEntityState.setDisableSnapshotTL(prev); // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
|
||||||
}
|
|
||||||
// Paper end
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
||||||
index c2552c3706831f7012b5b449fa43c7d5990056a4..4e8a1d01a6c0afef92ae56cc4909af06d63e5268 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
|
||||||
@@ -961,6 +961,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 BlockPosition 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 block, int flag) {
|
|
||||||
// Suppress during worldgen
|
|
||||||
@@ -972,7 +994,10 @@ public class CraftEventFactory {
|
|
||||||
CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag);
|
|
||||||
state.setData(block);
|
|
||||||
|
|
||||||
- BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.sourceBlockOverride != null ? CraftEventFactory.sourceBlockOverride : source), state);
|
|
||||||
+ // Leaf start - SparklyPaper parallel world ticking mod (collapse original behavior)
|
|
||||||
+ final BlockPos sourceBlockOverrideRTSnap = getSourceBlockOverrideRT();
|
|
||||||
+ BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, sourceBlockOverrideRTSnap != null ? sourceBlockOverrideRTSnap : source), state); // SparklyPaper - parallel world ticking
|
|
||||||
+ // Leaf end - SparklyPaper parallel world ticking mod (collapse original behavior)
|
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
|
||||||
|
|
||||||
if (!event.isCancelled()) {
|
|
||||||
@@ -2265,7 +2290,7 @@ public class CraftEventFactory {
|
|
||||||
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1));
|
|
||||||
|
|
||||||
org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to));
|
|
||||||
- if (!net.minecraft.world.level.block.DispenserBlock.eventFired) {
|
|
||||||
+ if (!net.minecraft.world.level.block.DispenserBlock.getEventFiredTL()) { // SparklyPaper - parallel world ticking // Leaf - SparklyPaper - parallel world ticking mod (collapse original behavior)
|
|
||||||
if (!event.callEvent()) {
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
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,11 @@
|
|||||||
|
package org.dreeam.leaf.async.world;
|
||||||
|
|
||||||
|
public enum ReadOperationType {
|
||||||
|
BLOCK_GET_BIOME,
|
||||||
|
BLOCK_GET_COMPUTED_BIOME,
|
||||||
|
BLOCK_IS_INDIRECTLY_POWERED,
|
||||||
|
BLOCK_GET_BLOCK_POWER,
|
||||||
|
BLOCK_RAY_TRACE,
|
||||||
|
BLOCK_CAN_PLACE,
|
||||||
|
BLOCK_GET_NMS_STATE
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.dreeam.leaf.async.world;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public record WorldReadRequest(
|
||||||
|
ReadOperationType type,
|
||||||
|
Object[] params, // Parameters for the read operation
|
||||||
|
CompletableFuture<Object> future // Future to complete with the result
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package org.dreeam.leaf.config.modules.network;
|
|||||||
|
|
||||||
import org.dreeam.leaf.config.ConfigModules;
|
import org.dreeam.leaf.config.ConfigModules;
|
||||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||||
|
import org.dreeam.leaf.protocol.DoABarrelRollPackets;
|
||||||
|
import org.dreeam.leaf.protocol.DoABarrelRollProtocol;
|
||||||
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import net.minecraft.world.level.ChunkPos;
|
|||||||
import org.dreeam.leaf.config.modules.misc.RegionFormatConfig;
|
import org.dreeam.leaf.config.modules.misc.RegionFormatConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
public class LinearRegionFile implements IRegionFile {
|
public class LinearRegionFile implements IRegionFile {
|
||||||
|
|
||||||
private static final long SUPERBLOCK = -4323716122432332390L;
|
private static final long SUPERBLOCK = -4323716122432332390L;
|
||||||
@@ -148,6 +150,7 @@ public class LinearRegionFile implements IRegionFile {
|
|||||||
// Save only once on shutdown
|
// Save only once on shutdown
|
||||||
if (!closed) return;
|
if (!closed) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long timestamp = getTimestamp();
|
long timestamp = getTimestamp();
|
||||||
short chunkCount = 0;
|
short chunkCount = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,405 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
|
||||||
Date: Sat, 17 Feb 2024 17:57:08 -0500
|
|
||||||
Subject: [PATCH] Rail Optimization: optimized PoweredRailBlock logic
|
|
||||||
|
|
||||||
Original project: https://github.com/FxMorin/RailOptimization
|
|
||||||
|
|
||||||
Full Rewrite of the powered rail iteration logic
|
|
||||||
that makes powered/activator rails turning on/off up to 4x faster.
|
|
||||||
This rewrite brings a massive performance boost while keeping the vanilla order. This is achieved by running all the
|
|
||||||
powered rail logic from a single rail instead of each block iterating separately. Which was not only very
|
|
||||||
expensive but also completely unnecessary and with a lot of massive overhead
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java
|
|
||||||
index bd14c08defe8afc5ceca59d16a5b1dbad178f594..b37ab12d4c51aca1576a14147a959188031d0fd7 100644
|
|
||||||
--- a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java
|
|
||||||
+++ b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java
|
|
||||||
@@ -29,7 +29,7 @@ public class PoweredRailBlock extends BaseRailBlock {
|
|
||||||
this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(PoweredRailBlock.POWERED, false)).setValue(PoweredRailBlock.WATERLOGGED, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
- protected boolean findPoweredRailSignal(Level world, BlockPos pos, BlockState state, boolean flag, int distance) {
|
|
||||||
+ public boolean findPoweredRailSignal(Level world, BlockPos pos, BlockState state, boolean flag, int distance) { // Leaf - Rail Optimization - protected -> public
|
|
||||||
if (distance >= world.purpurConfig.railActivationRange) { // Purpur
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
@@ -117,6 +117,12 @@ public class PoweredRailBlock extends BaseRailBlock {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void updateState(BlockState state, Level world, BlockPos pos, Block neighbor) {
|
|
||||||
+ // Leaf start - Rail Optimization
|
|
||||||
+ if (org.dreeam.leaf.config.modules.opt.OptimizedPoweredRails.enabled) {
|
|
||||||
+ org.dreeam.leaf.optimize.OptimizedPoweredRails.customUpdateState(this, state, world, pos);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ // Leaf end - Rail Optimization
|
|
||||||
boolean flag = (Boolean) state.getValue(PoweredRailBlock.POWERED);
|
|
||||||
boolean flag1 = world.hasNeighborSignal(pos) || this.findPoweredRailSignal(world, pos, state, true, 0) || this.findPoweredRailSignal(world, pos, state, false, 0);
|
|
||||||
|
|
||||||
diff --git a/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizedPoweredRails.java b/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizedPoweredRails.java
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000000000000000000000000000..ded3c385fcfc6c35086f76bed1b2223a6a29a43e
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizedPoweredRails.java
|
|
||||||
@@ -0,0 +1,18 @@
|
|
||||||
+package org.dreeam.leaf.config.modules.opt;
|
|
||||||
+
|
|
||||||
+import org.dreeam.leaf.config.ConfigModules;
|
|
||||||
+import org.dreeam.leaf.config.EnumConfigCategory;
|
|
||||||
+
|
|
||||||
+public class OptimizedPoweredRails extends ConfigModules {
|
|
||||||
+
|
|
||||||
+ public String getBasePath() {
|
|
||||||
+ return EnumConfigCategory.PERF.getBaseKeyName() + ".optimized-powered-rails";
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static boolean enabled = true;
|
|
||||||
+
|
|
||||||
+ @Override
|
|
||||||
+ public void onLoaded() {
|
|
||||||
+ enabled = config().getBoolean(getBasePath(), enabled);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
diff --git a/src/main/java/org/dreeam/leaf/optimize/OptimizedPoweredRails.java b/src/main/java/org/dreeam/leaf/optimize/OptimizedPoweredRails.java
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000000000000000000000000000..9e8bc27585e204aa2df77a90418bbe9e00bcd040
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/src/main/java/org/dreeam/leaf/optimize/OptimizedPoweredRails.java
|
|
||||||
@@ -0,0 +1,335 @@
|
|
||||||
+package org.dreeam.leaf.optimize;
|
|
||||||
+
|
|
||||||
+import net.minecraft.core.BlockPos;
|
|
||||||
+import net.minecraft.core.Direction;
|
|
||||||
+import net.minecraft.world.level.Level;
|
|
||||||
+import net.minecraft.world.level.block.Block;
|
|
||||||
+import net.minecraft.world.level.block.PoweredRailBlock;
|
|
||||||
+import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
+import net.minecraft.world.level.block.state.properties.RailShape;
|
|
||||||
+
|
|
||||||
+import java.util.HashMap;
|
|
||||||
+
|
|
||||||
+import static net.minecraft.world.level.block.Block.*;
|
|
||||||
+import static net.minecraft.world.level.block.PoweredRailBlock.POWERED;
|
|
||||||
+import static net.minecraft.world.level.block.PoweredRailBlock.SHAPE;
|
|
||||||
+
|
|
||||||
+public class OptimizedPoweredRails {
|
|
||||||
+
|
|
||||||
+ private static final Direction[] EAST_WEST_DIR = new Direction[]{Direction.WEST, Direction.EAST};
|
|
||||||
+ private static final Direction[] NORTH_SOUTH_DIR = new Direction[]{Direction.SOUTH, Direction.NORTH};
|
|
||||||
+
|
|
||||||
+ private static final int UPDATE_FORCE_PLACE = UPDATE_MOVE_BY_PISTON | UPDATE_KNOWN_SHAPE | UPDATE_CLIENTS;
|
|
||||||
+
|
|
||||||
+ public static int RAIL_POWER_LIMIT = 8;
|
|
||||||
+
|
|
||||||
+ public static void giveShapeUpdate(Level level, BlockState state, BlockPos pos, BlockPos fromPos, Direction direction) {
|
|
||||||
+ BlockState oldState = level.getBlockState(pos);
|
|
||||||
+ Block.updateOrDestroy(
|
|
||||||
+ oldState,
|
|
||||||
+ oldState.updateShape(direction.getOpposite(), state, level, pos, fromPos),
|
|
||||||
+ level,
|
|
||||||
+ pos,
|
|
||||||
+ UPDATE_CLIENTS & -34,
|
|
||||||
+ 0
|
|
||||||
+ );
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static void setRailPowerLimit(int powerLimit) {
|
|
||||||
+ RAIL_POWER_LIMIT = powerLimit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static void customUpdateState(PoweredRailBlock self, BlockState state, Level level, BlockPos pos) {
|
|
||||||
+ boolean shouldBePowered = level.hasNeighborSignal(pos) ||
|
|
||||||
+ self.findPoweredRailSignal(level, pos, state, true, 0) ||
|
|
||||||
+ self.findPoweredRailSignal(level, pos, state, false, 0);
|
|
||||||
+ if (shouldBePowered != state.getValue(POWERED)) {
|
|
||||||
+ RailShape railShape = state.getValue(SHAPE);
|
|
||||||
+ if (railShape.isAscending()) {
|
|
||||||
+ level.setBlock(pos, state.setValue(POWERED, shouldBePowered), 3);
|
|
||||||
+ level.updateNeighborsAtExceptFromFacing(pos.below(), self, Direction.UP);
|
|
||||||
+ level.updateNeighborsAtExceptFromFacing(pos.above(), self, Direction.DOWN); //isAscending
|
|
||||||
+ } else if (shouldBePowered) {
|
|
||||||
+ powerLane(self, level, pos, state, railShape);
|
|
||||||
+ } else {
|
|
||||||
+ dePowerLane(self, level, pos, state, railShape);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ boolean bl, int distance, RailShape shape,
|
|
||||||
+ HashMap<BlockPos, Boolean> checkedPos) {
|
|
||||||
+ BlockState blockState = world.getBlockState(pos);
|
|
||||||
+ boolean speedCheck = checkedPos.containsKey(pos) && checkedPos.get(pos);
|
|
||||||
+ if (speedCheck) {
|
|
||||||
+ return world.hasNeighborSignal(pos) ||
|
|
||||||
+ findPoweredRailSignalFaster(self, world, pos, blockState, bl, distance + 1, checkedPos);
|
|
||||||
+ } else {
|
|
||||||
+ if (blockState.is(self)) {
|
|
||||||
+ RailShape railShape = blockState.getValue(SHAPE);
|
|
||||||
+ if (shape == RailShape.EAST_WEST && (
|
|
||||||
+ railShape == RailShape.NORTH_SOUTH ||
|
|
||||||
+ railShape == RailShape.ASCENDING_NORTH ||
|
|
||||||
+ railShape == RailShape.ASCENDING_SOUTH
|
|
||||||
+ ) || shape == RailShape.NORTH_SOUTH && (
|
|
||||||
+ railShape == RailShape.EAST_WEST ||
|
|
||||||
+ railShape == RailShape.ASCENDING_EAST ||
|
|
||||||
+ railShape == RailShape.ASCENDING_WEST
|
|
||||||
+ )) {
|
|
||||||
+ return false;
|
|
||||||
+ } else if (blockState.getValue(POWERED)) {
|
|
||||||
+ return world.hasNeighborSignal(pos) ||
|
|
||||||
+ findPoweredRailSignalFaster(self, world, pos, blockState, bl, distance + 1, checkedPos);
|
|
||||||
+ } else {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level level,
|
|
||||||
+ BlockPos pos, BlockState state, boolean bl, int distance,
|
|
||||||
+ HashMap<BlockPos, Boolean> checkedPos) {
|
|
||||||
+ if (distance >= RAIL_POWER_LIMIT - 1) return false;
|
|
||||||
+ int i = pos.getX();
|
|
||||||
+ int j = pos.getY();
|
|
||||||
+ int k = pos.getZ();
|
|
||||||
+ boolean bl2 = true;
|
|
||||||
+ RailShape railShape = state.getValue(SHAPE);
|
|
||||||
+ switch (railShape.ordinal()) {
|
|
||||||
+ case 0 -> {
|
|
||||||
+ if (bl) ++k;
|
|
||||||
+ else --k;
|
|
||||||
+ }
|
|
||||||
+ case 1 -> {
|
|
||||||
+ if (bl) --i;
|
|
||||||
+ else ++i;
|
|
||||||
+ }
|
|
||||||
+ case 2 -> {
|
|
||||||
+ if (bl) {
|
|
||||||
+ --i;
|
|
||||||
+ } else {
|
|
||||||
+ ++i;
|
|
||||||
+ ++j;
|
|
||||||
+ bl2 = false;
|
|
||||||
+ }
|
|
||||||
+ railShape = RailShape.EAST_WEST;
|
|
||||||
+ }
|
|
||||||
+ case 3 -> {
|
|
||||||
+ if (bl) {
|
|
||||||
+ --i;
|
|
||||||
+ ++j;
|
|
||||||
+ bl2 = false;
|
|
||||||
+ } else {
|
|
||||||
+ ++i;
|
|
||||||
+ }
|
|
||||||
+ railShape = RailShape.EAST_WEST;
|
|
||||||
+ }
|
|
||||||
+ case 4 -> {
|
|
||||||
+ if (bl) {
|
|
||||||
+ ++k;
|
|
||||||
+ } else {
|
|
||||||
+ --k;
|
|
||||||
+ ++j;
|
|
||||||
+ bl2 = false;
|
|
||||||
+ }
|
|
||||||
+ railShape = RailShape.NORTH_SOUTH;
|
|
||||||
+ }
|
|
||||||
+ case 5 -> {
|
|
||||||
+ if (bl) {
|
|
||||||
+ ++k;
|
|
||||||
+ ++j;
|
|
||||||
+ bl2 = false;
|
|
||||||
+ } else {
|
|
||||||
+ --k;
|
|
||||||
+ }
|
|
||||||
+ railShape = RailShape.NORTH_SOUTH;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return findPoweredRailSignalFaster(
|
|
||||||
+ self, level, new BlockPos(i, j, k),
|
|
||||||
+ bl, distance, railShape, checkedPos
|
|
||||||
+ ) ||
|
|
||||||
+ (bl2 && findPoweredRailSignalFaster(
|
|
||||||
+ self, level, new BlockPos(i, j - 1, k),
|
|
||||||
+ bl, distance, railShape, checkedPos
|
|
||||||
+ ));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static void powerLane(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ BlockState mainState, RailShape railShape) {
|
|
||||||
+ world.setBlock(pos, mainState.setValue(POWERED, true), UPDATE_FORCE_PLACE);
|
|
||||||
+ HashMap<BlockPos, Boolean> checkedPos = new HashMap<>();
|
|
||||||
+ checkedPos.put(pos, true);
|
|
||||||
+ int[] count = new int[2];
|
|
||||||
+ if (railShape == RailShape.NORTH_SOUTH) { //Order: +z, -z
|
|
||||||
+ for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
|
||||||
+ setRailPositionsPower(self, world, pos, checkedPos, count, i, NORTH_SOUTH_DIR[i]);
|
|
||||||
+ }
|
|
||||||
+ updateRails(self, false, world, pos, mainState, count);
|
|
||||||
+ } else if (railShape == RailShape.EAST_WEST) { //Order: -x, +x
|
|
||||||
+ for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
|
||||||
+ setRailPositionsPower(self, world, pos, checkedPos, count, i, EAST_WEST_DIR[i]);
|
|
||||||
+ }
|
|
||||||
+ updateRails(self, true, world, pos, mainState, count);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static void dePowerLane(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ BlockState mainState, RailShape railShape) {
|
|
||||||
+ world.setBlock(pos, mainState.setValue(POWERED, false), UPDATE_FORCE_PLACE);
|
|
||||||
+ int[] count = new int[2];
|
|
||||||
+ if (railShape == RailShape.NORTH_SOUTH) { //Order: +z, -z
|
|
||||||
+ for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
|
||||||
+ setRailPositionsDePower(self, world, pos, count, i, NORTH_SOUTH_DIR[i]);
|
|
||||||
+ }
|
|
||||||
+ updateRails(self, false, world, pos, mainState, count);
|
|
||||||
+ } else if (railShape == RailShape.EAST_WEST) { //Order: -x, +x
|
|
||||||
+ for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
|
||||||
+ setRailPositionsDePower(self, world, pos, count, i, EAST_WEST_DIR[i]);
|
|
||||||
+ }
|
|
||||||
+ updateRails(self, true, world, pos, mainState, count);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void setRailPositionsPower(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ HashMap<BlockPos, Boolean> checkedPos, int[] count, int i, Direction dir) {
|
|
||||||
+ for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
|
||||||
+ BlockPos newPos = pos.relative(dir, z);
|
|
||||||
+ BlockState state = world.getBlockState(newPos);
|
|
||||||
+ if (checkedPos.containsKey(newPos)) {
|
|
||||||
+ if (!checkedPos.get(newPos)) break;
|
|
||||||
+ count[i]++;
|
|
||||||
+ } else if (!state.is(self) || state.getValue(POWERED) || !(
|
|
||||||
+ world.hasNeighborSignal(newPos) ||
|
|
||||||
+ findPoweredRailSignalFaster(self, world, newPos, state, true, 0, checkedPos) ||
|
|
||||||
+ findPoweredRailSignalFaster(self, world, newPos, state, false, 0, checkedPos)
|
|
||||||
+ )) {
|
|
||||||
+ checkedPos.put(newPos, false);
|
|
||||||
+ break;
|
|
||||||
+ } else {
|
|
||||||
+ checkedPos.put(newPos, true);
|
|
||||||
+ world.setBlock(newPos, state.setValue(POWERED, true), UPDATE_FORCE_PLACE);
|
|
||||||
+ count[i]++;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void setRailPositionsDePower(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ int[] count, int i, Direction dir) {
|
|
||||||
+ for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
|
||||||
+ BlockPos newPos = pos.relative(dir, z);
|
|
||||||
+ BlockState state = world.getBlockState(newPos);
|
|
||||||
+ if (!state.is(self) || !state.getValue(POWERED) || world.hasNeighborSignal(newPos) ||
|
|
||||||
+ self.findPoweredRailSignal(world, newPos, state, true, 0) ||
|
|
||||||
+ self.findPoweredRailSignal(world, newPos, state, false, 0)) break;
|
|
||||||
+ world.setBlock(newPos, state.setValue(POWERED, false), UPDATE_FORCE_PLACE);
|
|
||||||
+ count[i]++;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void shapeUpdateEnd(PoweredRailBlock self, Level world, BlockPos pos, BlockState mainState,
|
|
||||||
+ int endPos, Direction direction, int currentPos, BlockPos blockPos) {
|
|
||||||
+ if (currentPos == endPos) {
|
|
||||||
+ BlockPos newPos = pos.relative(direction, currentPos + 1);
|
|
||||||
+ OptimizedPoweredRails.giveShapeUpdate(world, mainState, newPos, pos, direction);
|
|
||||||
+ BlockState state = world.getBlockState(blockPos);
|
|
||||||
+ if (state.is(self) && state.getValue(SHAPE).isAscending())
|
|
||||||
+ OptimizedPoweredRails.giveShapeUpdate(world, mainState, newPos.above(), pos, direction);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void neighborUpdateEnd(PoweredRailBlock self, Level world, BlockPos pos, int endPos,
|
|
||||||
+ Direction direction, Block block, int currentPos, BlockPos blockPos) {
|
|
||||||
+ if (currentPos == endPos) {
|
|
||||||
+ BlockPos newPos = pos.relative(direction, currentPos + 1);
|
|
||||||
+ world.neighborChanged(newPos, block, pos);
|
|
||||||
+ BlockState state = world.getBlockState(blockPos);
|
|
||||||
+ if (state.is(self) && state.getValue(SHAPE).isAscending())
|
|
||||||
+ world.neighborChanged(newPos.above(), block, blockPos);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void updateRailsSectionEastWestShape(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ int c, BlockState mainState, Direction dir,
|
|
||||||
+ int[] count, int countAmt) {
|
|
||||||
+ BlockPos pos1 = pos.relative(dir, c);
|
|
||||||
+ if (c == 0 && count[1] == 0)
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite());
|
|
||||||
+ shapeUpdateEnd(self, world, pos, mainState, countAmt, dir, c, pos1);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.north(), pos, Direction.NORTH);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.south(), pos, Direction.SOUTH);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void updateRailsSectionNorthSouthShape(PoweredRailBlock self, Level world, BlockPos pos,
|
|
||||||
+ int c, BlockState mainState, Direction dir,
|
|
||||||
+ int[] count, int countAmt) {
|
|
||||||
+ BlockPos pos1 = pos.relative(dir, c);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.west(), pos, Direction.WEST);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.east(), pos, Direction.EAST);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN);
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP);
|
|
||||||
+ shapeUpdateEnd(self, world, pos, mainState, countAmt, dir, c, pos1);
|
|
||||||
+ if (c == 0 && count[1] == 0)
|
|
||||||
+ giveShapeUpdate(world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static void updateRails(PoweredRailBlock self, boolean eastWest, Level world,
|
|
||||||
+ BlockPos pos, BlockState mainState, int[] count) {
|
|
||||||
+ if (eastWest) {
|
|
||||||
+ for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
|
||||||
+ int countAmt = count[i];
|
|
||||||
+ if (i == 1 && countAmt == 0) continue;
|
|
||||||
+ Direction dir = EAST_WEST_DIR[i];
|
|
||||||
+ Block block = mainState.getBlock();
|
|
||||||
+ for (int c = countAmt; c >= i; c--) {
|
|
||||||
+ BlockPos p = pos.relative(dir, c);
|
|
||||||
+ if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, pos);
|
|
||||||
+ neighborUpdateEnd(self, world, pos, countAmt, dir, block, c, p);
|
|
||||||
+ world.neighborChanged(p.below(), block, pos);
|
|
||||||
+ world.neighborChanged(p.above(), block, pos);
|
|
||||||
+ world.neighborChanged(p.north(), block, pos);
|
|
||||||
+ world.neighborChanged(p.south(), block, pos);
|
|
||||||
+ BlockPos pos2 = pos.relative(dir, c).below();
|
|
||||||
+ world.neighborChanged(pos2.below(), block, pos);
|
|
||||||
+ world.neighborChanged(pos2.north(), block, pos);
|
|
||||||
+ world.neighborChanged(pos2.south(), block, pos);
|
|
||||||
+ if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, pos);
|
|
||||||
+ if (c == 0 && count[1] == 0)
|
|
||||||
+ world.neighborChanged(p.relative(dir.getOpposite()).below(), block, pos);
|
|
||||||
+ }
|
|
||||||
+ for (int c = countAmt; c >= i; c--)
|
|
||||||
+ updateRailsSectionEastWestShape(self, world, pos, c, mainState, dir, count, countAmt);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
|
||||||
+ int countAmt = count[i];
|
|
||||||
+ if (i == 1 && countAmt == 0) continue;
|
|
||||||
+ Direction dir = NORTH_SOUTH_DIR[i];
|
|
||||||
+ Block block = mainState.getBlock();
|
|
||||||
+ for (int c = countAmt; c >= i; c--) {
|
|
||||||
+ BlockPos p = pos.relative(dir, c);
|
|
||||||
+ world.neighborChanged(p.west(), block, pos);
|
|
||||||
+ world.neighborChanged(p.east(), block, pos);
|
|
||||||
+ world.neighborChanged(p.below(), block, pos);
|
|
||||||
+ world.neighborChanged(p.above(), block, pos);
|
|
||||||
+ neighborUpdateEnd(self, world, pos, countAmt, dir, block, c, p);
|
|
||||||
+ if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, pos);
|
|
||||||
+ BlockPos pos2 = pos.relative(dir, c).below();
|
|
||||||
+ world.neighborChanged(pos2.west(), block, pos);
|
|
||||||
+ world.neighborChanged(pos2.east(), block, pos);
|
|
||||||
+ world.neighborChanged(pos2.below(), block, pos);
|
|
||||||
+ if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, pos);
|
|
||||||
+ if (c == 0 && count[1] == 0)
|
|
||||||
+ world.neighborChanged(p.relative(dir.getOpposite()).below(), block, pos);
|
|
||||||
+ }
|
|
||||||
+ for (int c = countAmt; c >= i; c--)
|
|
||||||
+ updateRailsSectionNorthSouthShape(self, world, pos, c, mainState, dir, count, countAmt);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
\ No newline at end of file
|
|
||||||
@@ -15750,13 +15750,13 @@ index 248ac9bc820a96fc7653471308b18834fc735a77..ef70ba88e492904c426c7d35df442fa6
|
|||||||
}
|
}
|
||||||
// CraftBukkit end
|
// CraftBukkit end
|
||||||
diff --git a/net/minecraft/world/level/block/PoweredRailBlock.java b/net/minecraft/world/level/block/PoweredRailBlock.java
|
diff --git a/net/minecraft/world/level/block/PoweredRailBlock.java b/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
index 5ec12356e9f044d99762bf64a6d3bf74856d97a6..e80069d27ff60e0967d9333e2a0d6c8bf2f20a16 100644
|
index 6c64fc260669266869f7495ff07e1270dcb4ac75..a2202d2b4352be07b2445064339c61ba6a2521c7 100644
|
||||||
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
|
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
|
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
@@ -28,7 +28,7 @@ public class PoweredRailBlock extends BaseRailBlock {
|
@@ -28,7 +28,7 @@ public class PoweredRailBlock extends BaseRailBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean searchForward, int recursionCount) {
|
public boolean findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean searchForward, int recursionCount) {
|
||||||
- if (recursionCount >= 8) {
|
- if (recursionCount >= 8) {
|
||||||
+ if (recursionCount >= level.purpurConfig.railActivationRange) { // Purpur - Config for powered rail activation distance
|
+ if (recursionCount >= level.purpurConfig.railActivationRange) { // Purpur - Config for powered rail activation distance
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ index 35fd539eb2bfe60ad17ab1e558a01273666acc54..445bbdc8da7f1fdbddfc4d8787d78fea
|
|||||||
this.values[this.vp++ & 0xFF] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
|
this.values[this.vp++ & 0xFF] = (int)(l * 100L / Runtime.getRuntime().maxMemory());
|
||||||
this.repaint();
|
this.repaint();
|
||||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
index d2c1da7df4961fddbb7db952d817f127ece275d9..39d4ae0ae1ec89007fe1c86dc8d3409902890552 100644
|
index 35ca166964e8436154891708f69ac010491b64aa..586c00610fdba178f27391820d623c3a5254529f 100644
|
||||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
@@ -1289,7 +1289,7 @@ public class ServerGamePacketListenerImpl
|
@@ -1289,7 +1289,7 @@ public class ServerGamePacketListenerImpl
|
||||||
@@ -78,7 +78,7 @@ index d2c1da7df4961fddbb7db952d817f127ece275d9..39d4ae0ae1ec89007fe1c86dc8d34099
|
|||||||
this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect
|
this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect
|
||||||
return;
|
return;
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index 30e341bd5fca8b95d6911ca94f4aac17962f3269..55854dbacef9b3da9f12f67be21dd49007ea3c45 100644
|
index b714c64a318d38e309351f34426406c70d35d384..4e3b73bee5dae2b5921db86cc53b4cd9ebbd06f8 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -522,23 +522,36 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -522,23 +522,36 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
@@ -128,7 +128,7 @@ index 30e341bd5fca8b95d6911ca94f4aac17962f3269..55854dbacef9b3da9f12f67be21dd490
|
|||||||
public Entity(EntityType<?> entityType, Level level) {
|
public Entity(EntityType<?> entityType, Level level) {
|
||||||
this.type = entityType;
|
this.type = entityType;
|
||||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
index eb17ef1e0c350e97149452dbdc79398d71370fb1..d265278a56575529198735c113fa72c53b541669 100644
|
index cd8c764f9aa2321c6e157abe958d89868a9f7bd1..ed15b5f29658d799a36dcbd196a8fcb107be4bda 100644
|
||||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
@@ -1024,13 +1024,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
@@ -1024,13 +1024,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
@@ -150,7 +150,7 @@ index eb17ef1e0c350e97149452dbdc79398d71370fb1..d265278a56575529198735c113fa72c5
|
|||||||
}
|
}
|
||||||
// Purpur end - Mob head visibility percent
|
// Purpur end - Mob head visibility percent
|
||||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||||
index ba2f9ab55e52e25788b38c81e1070ae953b66371..33c99f3b24596fbbf3283b455ea8bf340203e01b 100644
|
index 6a94f42c8e048985b94db64fa0405e12824a8a0f..fbcf26c0bfb9f496c99bd5a2ba988be06162cd52 100644
|
||||||
--- a/net/minecraft/world/entity/Mob.java
|
--- a/net/minecraft/world/entity/Mob.java
|
||||||
+++ b/net/minecraft/world/entity/Mob.java
|
+++ b/net/minecraft/world/entity/Mob.java
|
||||||
@@ -1505,10 +1505,6 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
@@ -1505,10 +1505,6 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||||
@@ -279,7 +279,7 @@ index 584955d151e95727406bc68d6a6f15a33c0f920c..865a83fc73d79893e9bdedad37a6e398
|
|||||||
HoglinAi.updateActivity(this);
|
HoglinAi.updateActivity(this);
|
||||||
if (this.isConverting()) {
|
if (this.isConverting()) {
|
||||||
diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||||
index bac328ebdf9f94d156211e03d3913157e2b80374..bf1b33b7bb71ec8387d95d9089f199627a041945 100644
|
index 0afdfdc07764a26316c171c2a6722caf786875f2..732d44372cf226ca9d008ebc26d1838237ec96d6 100644
|
||||||
--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
|
--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||||
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||||
@@ -357,8 +357,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
@@ -357,8 +357,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
||||||
@@ -293,7 +293,7 @@ index bac328ebdf9f94d156211e03d3913157e2b80374..bf1b33b7bb71ec8387d95d9089f19962
|
|||||||
PiglinAi.updateActivity(this);
|
PiglinAi.updateActivity(this);
|
||||||
super.customServerAiStep(level);
|
super.customServerAiStep(level);
|
||||||
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
|
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
|
||||||
index bde9370798c037c494a9c73f328cb251e68c21b1..3a6be0122d49b20f78be6cc8f1c7acb5c2e45f39 100644
|
index 9f1c07be83999b7bafdee9238e8bad8c646d42f1..554e679a756dc1bf529053594231a958717f3573 100644
|
||||||
--- a/net/minecraft/world/entity/projectile/Projectile.java
|
--- a/net/minecraft/world/entity/projectile/Projectile.java
|
||||||
+++ b/net/minecraft/world/entity/projectile/Projectile.java
|
+++ b/net/minecraft/world/entity/projectile/Projectile.java
|
||||||
@@ -85,7 +85,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
@@ -85,7 +85,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||||
@@ -305,3 +305,21 @@ index bde9370798c037c494a9c73f328cb251e68c21b1..3a6be0122d49b20f78be6cc8f1c7acb5
|
|||||||
} else if (maxProjectileChunkLoadsConfig.perProjectile.resetMovementAfterReachLimit) {
|
} else if (maxProjectileChunkLoadsConfig.perProjectile.resetMovementAfterReachLimit) {
|
||||||
this.setDeltaMovement(0, this.getDeltaMovement().y, 0);
|
this.setDeltaMovement(0, this.getDeltaMovement().y, 0);
|
||||||
}
|
}
|
||||||
|
diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
|
index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..cadfbb7310fce33eda24d69c39fda5689c7fb882 100644
|
||||||
|
--- a/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
|
+++ b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
|
@@ -2435,6 +2435,13 @@ public class PurpurWorldConfig {
|
||||||
|
piglinMobGriefingOverride = getBooleanOrDefault("mobs.piglin.mob-griefing-override", piglinMobGriefingOverride);
|
||||||
|
piglinTakeDamageFromWater = getBoolean("mobs.piglin.takes-damage-from-water", piglinTakeDamageFromWater);
|
||||||
|
piglinPortalSpawnModifier = getInt("mobs.piglin.portal-spawn-modifier", piglinPortalSpawnModifier);
|
||||||
|
+ // Leaf start - Fix Pufferfish and Purpur patches - better input sanitization
|
||||||
|
+ if (piglinPortalSpawnModifier < 1) {
|
||||||
|
+ piglinPortalSpawnModifier = 1;
|
||||||
|
+ log(Level.WARNING, "mobs.piglin.portal-spawn-modifier is set to below minimum allowed value of 1");
|
||||||
|
+ log(Level.WARNING, "Using value of 1 to prevent issues");
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Fix Pufferfish and Purpur patches - better input sanitization
|
||||||
|
piglinAlwaysDropExp = getBoolean("mobs.piglin.always-drop-exp", piglinAlwaysDropExp);
|
||||||
|
piglinHeadVisibilityPercent = getDouble("mobs.piglin.head-visibility-percent", piglinHeadVisibilityPercent);
|
||||||
|
piglinIgnoresArmorWithGoldTrim = getBoolean("mobs.piglin.ignores-armor-with-gold-trim", piglinIgnoresArmorWithGoldTrim);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ This patch was ported downstream from the Petal fork.
|
|||||||
Makes most pathfinding-related work happen asynchronously
|
Makes most pathfinding-related work happen asynchronously
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||||
index 33c99f3b24596fbbf3283b455ea8bf340203e01b..e9ebf23b0b1af85e3738a70acc0eaa3e8980261f 100644
|
index fbcf26c0bfb9f496c99bd5a2ba988be06162cd52..cf136bc3d0d285ebde23c6e31c002933564fdcb2 100644
|
||||||
--- a/net/minecraft/world/entity/Mob.java
|
--- a/net/minecraft/world/entity/Mob.java
|
||||||
+++ b/net/minecraft/world/entity/Mob.java
|
+++ b/net/minecraft/world/entity/Mob.java
|
||||||
@@ -243,6 +243,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
@@ -243,6 +243,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||||
@@ -560,19 +560,20 @@ index 1f96fd5085bacb4c584576c7cb9f51e7898e9b03..03b6c8c8dcd42e864751e68be9d35d20
|
|||||||
+ // Leaf end - Kaiiju - await on async path processing
|
+ // Leaf end - Kaiiju - await on async path processing
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java
|
diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java
|
||||||
index e9dfff7e3726cd2229f89bb39fa1ca4815d99a6d..654ecd20ef4a43f7ffc447c15434ce46ab89efe9 100644
|
index e9dfff7e3726cd2229f89bb39fa1ca4815d99a6d..04c0dad21c4cdd464a8ebe830bcdd217bb4156ec 100644
|
||||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||||
@@ -936,7 +936,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
@@ -936,7 +936,8 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||||
} else {
|
} else {
|
||||||
Bee.this.pathfindRandomlyTowards(Bee.this.hivePos);
|
Bee.this.pathfindRandomlyTowards(Bee.this.hivePos);
|
||||||
}
|
}
|
||||||
- } else {
|
- } else {
|
||||||
+ } else if (navigation.getPath() != null && navigation.getPath().isProcessed()) { // Kaiiju - petal - check processing
|
+ //} else if (navigation.getPath() != null && navigation.getPath().isProcessed()) { // Kaiiju - petal - check processing // todo
|
||||||
|
+ } else {
|
||||||
boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos);
|
boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos);
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
this.dropAndBlacklistHive();
|
this.dropAndBlacklistHive();
|
||||||
@@ -990,7 +990,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
@@ -990,7 +991,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Path path = Bee.this.navigation.getPath();
|
Path path = Bee.this.navigation.getPath();
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ index 39489c8a347031fb4f73faca46039786e35762ac..4de1d0966157b20526386becee10b9be
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java
|
diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552c53a42c5 100644
|
index cadfbb7310fce33eda24d69c39fda5689c7fb882..21765347d7a81f4111f23685f699286d5e5cccb6 100644
|
||||||
--- a/org/purpurmc/purpur/PurpurWorldConfig.java
|
--- a/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
+++ b/org/purpurmc/purpur/PurpurWorldConfig.java
|
+++ b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
@@ -1625,6 +1625,7 @@ public class PurpurWorldConfig {
|
@@ -1625,6 +1625,7 @@ public class PurpurWorldConfig {
|
||||||
@@ -118,7 +118,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean illusionerRidable = false;
|
public boolean illusionerRidable = false;
|
||||||
@@ -3417,6 +3421,7 @@ public class PurpurWorldConfig {
|
@@ -3424,6 +3428,7 @@ public class PurpurWorldConfig {
|
||||||
public boolean zombieTakeDamageFromWater = false;
|
public boolean zombieTakeDamageFromWater = false;
|
||||||
public boolean zombieAlwaysDropExp = false;
|
public boolean zombieAlwaysDropExp = false;
|
||||||
public double zombieHeadVisibilityPercent = 0.5D;
|
public double zombieHeadVisibilityPercent = 0.5D;
|
||||||
@@ -126,7 +126,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
private void zombieSettings() {
|
private void zombieSettings() {
|
||||||
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
|
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
|
||||||
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
|
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
|
||||||
@@ -3442,6 +3447,7 @@ public class PurpurWorldConfig {
|
@@ -3449,6 +3454,7 @@ public class PurpurWorldConfig {
|
||||||
zombieTakeDamageFromWater = getBoolean("mobs.zombie.takes-damage-from-water", zombieTakeDamageFromWater);
|
zombieTakeDamageFromWater = getBoolean("mobs.zombie.takes-damage-from-water", zombieTakeDamageFromWater);
|
||||||
zombieAlwaysDropExp = getBoolean("mobs.zombie.always-drop-exp", zombieAlwaysDropExp);
|
zombieAlwaysDropExp = getBoolean("mobs.zombie.always-drop-exp", zombieAlwaysDropExp);
|
||||||
zombieHeadVisibilityPercent = getDouble("mobs.zombie.head-visibility-percent", zombieHeadVisibilityPercent);
|
zombieHeadVisibilityPercent = getDouble("mobs.zombie.head-visibility-percent", zombieHeadVisibilityPercent);
|
||||||
@@ -134,7 +134,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean zombieHorseRidable = false;
|
public boolean zombieHorseRidable = false;
|
||||||
@@ -3491,6 +3497,7 @@ public class PurpurWorldConfig {
|
@@ -3498,6 +3504,7 @@ public class PurpurWorldConfig {
|
||||||
public int zombieVillagerCuringTimeMax = 6000;
|
public int zombieVillagerCuringTimeMax = 6000;
|
||||||
public boolean zombieVillagerCureEnabled = true;
|
public boolean zombieVillagerCureEnabled = true;
|
||||||
public boolean zombieVillagerAlwaysDropExp = false;
|
public boolean zombieVillagerAlwaysDropExp = false;
|
||||||
@@ -142,7 +142,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
private void zombieVillagerSettings() {
|
private void zombieVillagerSettings() {
|
||||||
zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
|
zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
|
||||||
zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
|
zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
|
||||||
@@ -3511,6 +3518,7 @@ public class PurpurWorldConfig {
|
@@ -3518,6 +3525,7 @@ public class PurpurWorldConfig {
|
||||||
zombieVillagerCuringTimeMax = getInt("mobs.zombie_villager.curing_time.max", zombieVillagerCuringTimeMax);
|
zombieVillagerCuringTimeMax = getInt("mobs.zombie_villager.curing_time.max", zombieVillagerCuringTimeMax);
|
||||||
zombieVillagerCureEnabled = getBoolean("mobs.zombie_villager.cure.enabled", zombieVillagerCureEnabled);
|
zombieVillagerCureEnabled = getBoolean("mobs.zombie_villager.cure.enabled", zombieVillagerCureEnabled);
|
||||||
zombieVillagerAlwaysDropExp = getBoolean("mobs.zombie_villager.always-drop-exp", zombieVillagerAlwaysDropExp);
|
zombieVillagerAlwaysDropExp = getBoolean("mobs.zombie_villager.always-drop-exp", zombieVillagerAlwaysDropExp);
|
||||||
@@ -150,7 +150,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean zombifiedPiglinRidable = false;
|
public boolean zombifiedPiglinRidable = false;
|
||||||
@@ -3525,6 +3533,7 @@ public class PurpurWorldConfig {
|
@@ -3532,6 +3540,7 @@ public class PurpurWorldConfig {
|
||||||
public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = false;
|
public boolean zombifiedPiglinCountAsPlayerKillWhenAngry = false;
|
||||||
public boolean zombifiedPiglinTakeDamageFromWater = false;
|
public boolean zombifiedPiglinTakeDamageFromWater = false;
|
||||||
public boolean zombifiedPiglinAlwaysDropExp = false;
|
public boolean zombifiedPiglinAlwaysDropExp = false;
|
||||||
@@ -158,7 +158,7 @@ index 31cc4e6e68a9743aaaeb296cb31e64526d3f1f73..67739ba7cb82d615a5f0c4db7aaa5552
|
|||||||
private void zombifiedPiglinSettings() {
|
private void zombifiedPiglinSettings() {
|
||||||
zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable);
|
zombifiedPiglinRidable = getBoolean("mobs.zombified_piglin.ridable", zombifiedPiglinRidable);
|
||||||
zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater);
|
zombifiedPiglinRidableInWater = getBoolean("mobs.zombified_piglin.ridable-in-water", zombifiedPiglinRidableInWater);
|
||||||
@@ -3546,6 +3555,7 @@ public class PurpurWorldConfig {
|
@@ -3553,6 +3562,7 @@ public class PurpurWorldConfig {
|
||||||
zombifiedPiglinCountAsPlayerKillWhenAngry = getBoolean("mobs.zombified_piglin.count-as-player-kill-when-angry", zombifiedPiglinCountAsPlayerKillWhenAngry);
|
zombifiedPiglinCountAsPlayerKillWhenAngry = getBoolean("mobs.zombified_piglin.count-as-player-kill-when-angry", zombifiedPiglinCountAsPlayerKillWhenAngry);
|
||||||
zombifiedPiglinTakeDamageFromWater = getBoolean("mobs.zombified_piglin.takes-damage-from-water", zombifiedPiglinTakeDamageFromWater);
|
zombifiedPiglinTakeDamageFromWater = getBoolean("mobs.zombified_piglin.takes-damage-from-water", zombifiedPiglinTakeDamageFromWater);
|
||||||
zombifiedPiglinAlwaysDropExp = getBoolean("mobs.zombified_piglin.always-drop-exp", zombifiedPiglinAlwaysDropExp);
|
zombifiedPiglinAlwaysDropExp = getBoolean("mobs.zombified_piglin.always-drop-exp", zombifiedPiglinAlwaysDropExp);
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ index 234f123959830cc2adb78b9dc8752906140e5b11..e0dceff32b47b334ddcb76271e3cf3ea
|
|||||||
org.bukkit.event.inventory.InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27);
|
org.bukkit.event.inventory.InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27);
|
||||||
enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows);
|
enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows);
|
||||||
diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java
|
diff --git a/org/purpurmc/purpur/PurpurWorldConfig.java b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
index 67739ba7cb82d615a5f0c4db7aaa5552c53a42c5..d81e06592aa9521f866c2c910b43a7364de3796e 100644
|
index 21765347d7a81f4111f23685f699286d5e5cccb6..8459f5b9bf548e51b85e753a4e65dd86baa2b5df 100644
|
||||||
--- a/org/purpurmc/purpur/PurpurWorldConfig.java
|
--- a/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
+++ b/org/purpurmc/purpur/PurpurWorldConfig.java
|
+++ b/org/purpurmc/purpur/PurpurWorldConfig.java
|
||||||
@@ -1189,12 +1189,20 @@ public class PurpurWorldConfig {
|
@@ -1189,12 +1189,20 @@ public class PurpurWorldConfig {
|
||||||
@@ -353,7 +353,7 @@ index 67739ba7cb82d615a5f0c4db7aaa5552c53a42c5..d81e06592aa9521f866c2c910b43a736
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean ghastRidable = false;
|
public boolean ghastRidable = false;
|
||||||
@@ -2911,6 +2945,10 @@ public class PurpurWorldConfig {
|
@@ -2918,6 +2952,10 @@ public class PurpurWorldConfig {
|
||||||
public double snifferMaxHealth = 14.0D;
|
public double snifferMaxHealth = 14.0D;
|
||||||
public double snifferScale = 1.0D;
|
public double snifferScale = 1.0D;
|
||||||
public int snifferBreedingTicks = 6000;
|
public int snifferBreedingTicks = 6000;
|
||||||
@@ -364,7 +364,7 @@ index 67739ba7cb82d615a5f0c4db7aaa5552c53a42c5..d81e06592aa9521f866c2c910b43a736
|
|||||||
private void snifferSettings() {
|
private void snifferSettings() {
|
||||||
snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable);
|
snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable);
|
||||||
snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater);
|
snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater);
|
||||||
@@ -2918,6 +2956,10 @@ public class PurpurWorldConfig {
|
@@ -2925,6 +2963,10 @@ public class PurpurWorldConfig {
|
||||||
snifferMaxHealth = getDouble("mobs.sniffer.attributes.max_health", snifferMaxHealth);
|
snifferMaxHealth = getDouble("mobs.sniffer.attributes.max_health", snifferMaxHealth);
|
||||||
snifferScale = Mth.clamp(getDouble("mobs.sniffer.attributes.scale", snifferScale), 0.0625D, 16.0D);
|
snifferScale = Mth.clamp(getDouble("mobs.sniffer.attributes.scale", snifferScale), 0.0625D, 16.0D);
|
||||||
snifferBreedingTicks = getInt("mobs.sniffer.breeding-delay-ticks", snifferBreedingTicks);
|
snifferBreedingTicks = getInt("mobs.sniffer.breeding-delay-ticks", snifferBreedingTicks);
|
||||||
@@ -375,7 +375,7 @@ index 67739ba7cb82d615a5f0c4db7aaa5552c53a42c5..d81e06592aa9521f866c2c910b43a736
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean squidRidable = false;
|
public boolean squidRidable = false;
|
||||||
@@ -3019,10 +3061,20 @@ public class PurpurWorldConfig {
|
@@ -3026,10 +3068,20 @@ public class PurpurWorldConfig {
|
||||||
public boolean tadpoleRidable = false;
|
public boolean tadpoleRidable = false;
|
||||||
public boolean tadpoleRidableInWater = true;
|
public boolean tadpoleRidableInWater = true;
|
||||||
public boolean tadpoleControllable = true;
|
public boolean tadpoleControllable = true;
|
||||||
@@ -396,7 +396,7 @@ index 67739ba7cb82d615a5f0c4db7aaa5552c53a42c5..d81e06592aa9521f866c2c910b43a736
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean traderLlamaRidable = false;
|
public boolean traderLlamaRidable = false;
|
||||||
@@ -3256,10 +3308,20 @@ public class PurpurWorldConfig {
|
@@ -3263,10 +3315,20 @@ public class PurpurWorldConfig {
|
||||||
public boolean wardenRidable = false;
|
public boolean wardenRidable = false;
|
||||||
public boolean wardenRidableInWater = true;
|
public boolean wardenRidableInWater = true;
|
||||||
public boolean wardenControllable = true;
|
public boolean wardenControllable = true;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ index f861f9e087182470a3bbb22678dbdacb8a73e943..a3d0d17178eedfaef83e2e0df6b1c2d7
|
|||||||
|
|
||||||
private DensityFunction wrapNew(DensityFunction densityFunction) {
|
private DensityFunction wrapNew(DensityFunction densityFunction) {
|
||||||
diff --git a/net/minecraft/world/level/levelgen/SurfaceRules.java b/net/minecraft/world/level/levelgen/SurfaceRules.java
|
diff --git a/net/minecraft/world/level/levelgen/SurfaceRules.java b/net/minecraft/world/level/levelgen/SurfaceRules.java
|
||||||
index 0948c8db90605a15a043b5c5bc74edecd7f9db1b..009e8a270c25614d03413d8b8b1f39c2da8ba12f 100644
|
index 0948c8db90605a15a043b5c5bc74edecd7f9db1b..6cba88415a4715527e163e54662db9b3ab37c747 100644
|
||||||
--- a/net/minecraft/world/level/levelgen/SurfaceRules.java
|
--- a/net/minecraft/world/level/levelgen/SurfaceRules.java
|
||||||
+++ b/net/minecraft/world/level/levelgen/SurfaceRules.java
|
+++ b/net/minecraft/world/level/levelgen/SurfaceRules.java
|
||||||
@@ -313,8 +313,15 @@ public class SurfaceRules {
|
@@ -313,8 +313,15 @@ public class SurfaceRules {
|
||||||
@@ -48,9 +48,9 @@ index 0948c8db90605a15a043b5c5bc74edecd7f9db1b..009e8a270c25614d03413d8b8b1f39c2
|
|||||||
+ ++this.lastUpdateY;
|
+ ++this.lastUpdateY;
|
||||||
+ Supplier<Holder<Biome>> getter = this.biome;
|
+ Supplier<Holder<Biome>> getter = this.biome;
|
||||||
+ if (getter == null) {
|
+ if (getter == null) {
|
||||||
+ this.biome = getter = new org.dreeam.leaf.util.biome.PositionalBiomeGetter(this.biomeGetter, this.pos);
|
+ this.biome = getter = new org.dreeam.leaf.world.biome.PositionalBiomeGetter(this.biomeGetter, this.pos);
|
||||||
+ }
|
+ }
|
||||||
+ ((org.dreeam.leaf.util.biome.PositionalBiomeGetter) getter).update(blockX, blockY, blockZ);
|
+ ((org.dreeam.leaf.world.biome.PositionalBiomeGetter) getter).update(blockX, blockY, blockZ);
|
||||||
+ // Leaf end - Reduce worldgen allocations
|
+ // Leaf end - Reduce worldgen allocations
|
||||||
this.blockY = blockY;
|
this.blockY = blockY;
|
||||||
this.waterHeight = waterHeight;
|
this.waterHeight = waterHeight;
|
||||||
|
|||||||
@@ -23,6 +23,28 @@ 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
|
But it is still recommending to use those packet based, virtual entity
|
||||||
based NPC plugins, e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc.
|
based NPC plugins, e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc.
|
||||||
|
|
||||||
|
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
|
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..4200d22606c6a3dbdf282792a4007a51df66963b 100644
|
||||||
|
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
|
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
|
@@ -60,7 +60,16 @@ public final class NearbyPlayers {
|
||||||
|
|
||||||
|
private final ServerLevel world;
|
||||||
|
private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
|
||||||
|
- private final Long2ReferenceOpenHashMap<TrackedChunk> byChunk = new Long2ReferenceOpenHashMap<>();
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap<TrackedChunk> byChunk;
|
||||||
|
+ {
|
||||||
|
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
||||||
|
+ byChunk = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>());
|
||||||
|
+ } else {
|
||||||
|
+ byChunk = new Long2ReferenceOpenHashMap<>();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
private final Long2ReferenceOpenHashMap<ReferenceList<ServerPlayer>>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES];
|
||||||
|
{
|
||||||
|
for (int i = 0; i < this.directByChunk.length; ++i) {
|
||||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||||
index 02a9ef1694c796584c29430d27f0a09047368835..32608df3da169159c070f37cb55407f4f6187744 100644
|
index 02a9ef1694c796584c29430d27f0a09047368835..32608df3da169159c070f37cb55407f4f6187744 100644
|
||||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||||
@@ -36,8 +58,20 @@ index 02a9ef1694c796584c29430d27f0a09047368835..32608df3da169159c070f37cb55407f4
|
|||||||
|
|
||||||
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
|
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
|
||||||
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
|
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
|
||||||
|
diff --git a/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java b/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
index 9c0c99b936b4a82ebfe924866e53ec71f7bbe9ad..2ccff968cb2065d34fad4d27573f9e3081edb2f2 100644
|
||||||
|
--- a/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
+++ b/net/minecraft/network/protocol/game/ClientboundUpdateAttributesPacket.java
|
||||||
|
@@ -32,6 +32,7 @@ public class ClientboundUpdateAttributesPacket implements Packet<ClientGamePacke
|
||||||
|
this.attributes = Lists.newArrayList();
|
||||||
|
|
||||||
|
for (AttributeInstance attributeInstance : attributes) {
|
||||||
|
+ if (attributeInstance == null) continue; // Leaf - Multithreaded tracker
|
||||||
|
this.attributes
|
||||||
|
.add(
|
||||||
|
new ClientboundUpdateAttributesPacket.AttributeSnapshot(
|
||||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||||
index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e693645dfe 100644
|
index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..ae0a7c9b95f4f2561769e0d661fadbe29a2d6f8b 100644
|
||||||
--- a/net/minecraft/server/level/ChunkMap.java
|
--- a/net/minecraft/server/level/ChunkMap.java
|
||||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||||
@@ -255,6 +255,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -255,6 +255,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
@@ -70,14 +104,13 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
// Paper start - optimise entity tracker
|
// Paper start - optimise entity tracker
|
||||||
if (true) {
|
if (true) {
|
||||||
this.newTrackerTick();
|
this.newTrackerTick();
|
||||||
@@ -1135,7 +1151,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1135,7 +1151,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
final Entity entity;
|
final Entity entity;
|
||||||
private final int range;
|
private final int range;
|
||||||
SectionPos lastSectionPos;
|
SectionPos lastSectionPos;
|
||||||
- public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
- public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||||
+ // Leaf start - Multithreaded tracker
|
+ // Leaf start - Multithreaded tracker
|
||||||
+ public static final ServerPlayerConnection[] EMPTY_OBJECT_ARRAY = new ServerPlayerConnection[0];
|
+ public static final ServerPlayerConnection[] EMPTY_OBJECT_ARRAY = new ServerPlayerConnection[0];
|
||||||
+ public final Object sync = new Object();
|
|
||||||
+ public final Set<ServerPlayerConnection> seenBy = org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled ? it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>()) : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
+ public final Set<ServerPlayerConnection> seenBy = org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled ? it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>()) : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||||
+ private volatile ServerPlayerConnection[] seenByArray = EMPTY_OBJECT_ARRAY;
|
+ private volatile ServerPlayerConnection[] seenByArray = EMPTY_OBJECT_ARRAY;
|
||||||
+ public ServerPlayerConnection[] seenBy() {
|
+ public ServerPlayerConnection[] seenBy() {
|
||||||
@@ -90,7 +123,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
|
|
||||||
// Paper start - optimise entity tracker
|
// Paper start - optimise entity tracker
|
||||||
private long lastChunkUpdate = -1L;
|
private long lastChunkUpdate = -1L;
|
||||||
@@ -1162,27 +1189,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1162,27 +1188,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
this.lastTrackedChunk = chunk;
|
this.lastTrackedChunk = chunk;
|
||||||
|
|
||||||
final ServerPlayer[] playersRaw = players.getRawDataUnchecked();
|
final ServerPlayer[] playersRaw = players.getRawDataUnchecked();
|
||||||
@@ -191,7 +224,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(conn.getPlayer())) {
|
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(conn.getPlayer())) {
|
||||||
foundToRemove = true;
|
foundToRemove = true;
|
||||||
break;
|
break;
|
||||||
@@ -1193,12 +1288,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1193,12 +1287,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +240,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1208,10 +1304,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1208,10 +1303,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
if (this.seenBy.isEmpty()) {
|
if (this.seenBy.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -221,7 +254,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1238,7 +1335,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1238,7 +1334,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(Packet<?> packet) {
|
public void broadcast(Packet<?> packet) {
|
||||||
@@ -230,7 +263,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
serverPlayerConnection.send(packet);
|
serverPlayerConnection.send(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1259,21 +1356,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1259,21 +1355,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastRemoved() {
|
public void broadcastRemoved() {
|
||||||
@@ -268,7 +301,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
// Paper start - remove allocation of Vec3D here
|
// Paper start - remove allocation of Vec3D here
|
||||||
// Vec3 vec3 = player.position().subtract(this.entity.position());
|
// Vec3 vec3 = player.position().subtract(this.entity.position());
|
||||||
double vec3_dx = player.getX() - this.entity.getX();
|
double vec3_dx = player.getX() - this.entity.getX();
|
||||||
@@ -1301,6 +1411,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1301,6 +1410,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
// CraftBukkit end
|
// CraftBukkit end
|
||||||
if (flag) {
|
if (flag) {
|
||||||
if (this.seenBy.add(player.connection)) {
|
if (this.seenBy.add(player.connection)) {
|
||||||
@@ -276,7 +309,7 @@ index c60b9e4076450de2157c1a3cf4f98cc2c19e4e6a..41da66fd77924a9a4bd9cc12f517e2e6
|
|||||||
// Paper start - entity tracking events
|
// Paper start - entity tracking events
|
||||||
if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
|
if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) {
|
||||||
this.serverEntity.addPairing(player);
|
this.serverEntity.addPairing(player);
|
||||||
@@ -1309,6 +1420,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1309,6 +1419,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
this.serverEntity.onPlayerAdd(); // Paper - fix desync when a player is added to the tracker
|
this.serverEntity.onPlayerAdd(); // Paper - fix desync when a player is added to the tracker
|
||||||
}
|
}
|
||||||
} else if (this.seenBy.remove(player.connection)) {
|
} else if (this.seenBy.remove(player.connection)) {
|
||||||
@@ -298,18 +331,10 @@ index f106373ef3ac4a8685c2939c9e8361688a285913..51ae390c68e7a3aa193329cc3bc47ca6
|
|||||||
public boolean visible = true;
|
public boolean visible = true;
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||||
index 1a9601aee097b6c10cf2ae1c52fddf45da85f60f..867936866d952c559b6ffa49fdf78acd70a9bab9 100644
|
index 1a9601aee097b6c10cf2ae1c52fddf45da85f60f..16b2ca8c96e9561aa57e0903d1e98e6441044b6d 100644
|
||||||
--- a/net/minecraft/server/level/ServerEntity.java
|
--- a/net/minecraft/server/level/ServerEntity.java
|
||||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||||
@@ -75,6 +75,7 @@ public class ServerEntity {
|
@@ -146,7 +146,7 @@ public class ServerEntity {
|
||||||
@Nullable
|
|
||||||
private List<SynchedEntityData.DataValue<?>> trackedDataValues;
|
|
||||||
private final Set<net.minecraft.server.network.ServerPlayerConnection> trackedPlayers; // Paper
|
|
||||||
+ public boolean wantSendDirtyEntityData = false; // Leaf - Multithreaded tracker
|
|
||||||
|
|
||||||
public ServerEntity(
|
|
||||||
ServerLevel level,
|
|
||||||
@@ -146,7 +147,7 @@ public class ServerEntity {
|
|
||||||
MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
|
MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
|
||||||
MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level);
|
MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level);
|
||||||
if (savedData != null) {
|
if (savedData != null) {
|
||||||
@@ -318,21 +343,17 @@ index 1a9601aee097b6c10cf2ae1c52fddf45da85f60f..867936866d952c559b6ffa49fdf78acd
|
|||||||
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
|
final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
|
||||||
savedData.tickCarriedBy(serverPlayer, item);
|
savedData.tickCarriedBy(serverPlayer, item);
|
||||||
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
|
||||||
@@ -450,6 +451,12 @@ public class ServerEntity {
|
@@ -468,7 +468,7 @@ public class ServerEntity {
|
||||||
|
this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
|
||||||
|
}
|
||||||
|
|
||||||
|
- attributesToSync.clear();
|
||||||
|
+ // attributesToSync.clear(); // Leaf - Multithreaded tracker
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendDirtyEntityData() {
|
|
||||||
+ // Leaf start - Multithreaded tracker
|
|
||||||
+ if (Thread.currentThread() instanceof org.dreeam.leaf.async.tracker.MultithreadedTracker.MultithreadedTrackerThread) {
|
|
||||||
+ wantSendDirtyEntityData = true;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ // Leaf end - Multithreaded tracker
|
|
||||||
SynchedEntityData entityData = this.entity.getEntityData();
|
|
||||||
List<SynchedEntityData.DataValue<?>> list = entityData.packDirty();
|
|
||||||
if (list != null) {
|
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 5943b18f172fb1d77ef1fe768daa8e8f43c3c8c1..7b85a9ebdbe3e8bee0a8fc100ede8a3f07eee5ce 100644
|
index 42f56bd6a9f449df23f7e7f00b3efa114a003449..0471b04833fbca5dfc0cc6575692cdefb83edbed 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -2503,7 +2503,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2503,7 +2503,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -354,7 +375,7 @@ index 5943b18f172fb1d77ef1fe768daa8e8f43c3c8c1..7b85a9ebdbe3e8bee0a8fc100ede8a3f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
index 729f595491c7a4edf24dff2e876dfb69ade87a17..a3069b29a1b78012314747d705e27c167acd10b3 100644
|
index be803fd0a79850254bd4a7f64534142cd5b4ec98..6992a53abdcff6299bedf33ba0b1bc6386a1ea74 100644
|
||||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
@@ -1878,7 +1878,7 @@ public class ServerGamePacketListenerImpl
|
@@ -1878,7 +1878,7 @@ public class ServerGamePacketListenerImpl
|
||||||
@@ -366,6 +387,233 @@ index 729f595491c7a4edf24dff2e876dfb69ade87a17..a3069b29a1b78012314747d705e27c16
|
|||||||
// Paper start - Prevent teleporting dead entities
|
// Paper start - Prevent teleporting dead entities
|
||||||
if (this.player.isRemoved()) {
|
if (this.player.isRemoved()) {
|
||||||
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
||||||
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
index 4c3eadc2d8480b2a2c2c08e58620544d403d3adc..68241d1d488bc2848e3c0d167270c1788e573c37 100644
|
||||||
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
@@ -1317,13 +1317,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshDirtyAttributes() {
|
||||||
|
- Set<AttributeInstance> attributesToUpdate = this.getAttributes().getAttributesToUpdate();
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ int[] attributesToUpdate = this.getAttributes().getAttributesToUpdateIds();
|
||||||
|
|
||||||
|
- for (AttributeInstance attributeInstance : attributesToUpdate) {
|
||||||
|
- this.onAttributeUpdated(attributeInstance.getAttribute());
|
||||||
|
+ for (int attribute : attributesToUpdate) {
|
||||||
|
+ this.onAttributeUpdated(net.minecraft.core.registries.BuiltInRegistries.ATTRIBUTE.get(attribute).orElseThrow());
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- attributesToUpdate.clear();
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onAttributeUpdated(Holder<Attribute> attribute) {
|
||||||
|
diff --git a/net/minecraft/world/entity/ai/attributes/Attribute.java b/net/minecraft/world/entity/ai/attributes/Attribute.java
|
||||||
|
index f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b161647497f99b 100644
|
||||||
|
--- a/net/minecraft/world/entity/ai/attributes/Attribute.java
|
||||||
|
+++ b/net/minecraft/world/entity/ai/attributes/Attribute.java
|
||||||
|
@@ -16,10 +16,15 @@ public class Attribute {
|
||||||
|
private boolean syncable;
|
||||||
|
private final String descriptionId;
|
||||||
|
private Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE;
|
||||||
|
+ // Leaf start - Optimize AttributeMap
|
||||||
|
+ public final int uid;
|
||||||
|
+ private static final java.util.concurrent.atomic.AtomicInteger SIZE = new java.util.concurrent.atomic.AtomicInteger();
|
||||||
|
+ // Leaf end - Optimize AttributeMap
|
||||||
|
|
||||||
|
protected Attribute(String descriptionId, double defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.descriptionId = descriptionId;
|
||||||
|
+ this.uid = SIZE.getAndAdd(1); // Leaf - Optimize AttributeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDefaultValue() {
|
||||||
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
|
index 3ac9f36eae87369354e992a1d9b5c5b2d87d17cb..9f09d78a7dac12c7f1b06029d32ad93fae0c2aec 100644
|
||||||
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
|
@@ -26,8 +26,24 @@ public class AttributeInstance {
|
||||||
|
private final Map<AttributeModifier.Operation, Map<ResourceLocation, AttributeModifier>> modifiersByOperation = Maps.newEnumMap(
|
||||||
|
AttributeModifier.Operation.class
|
||||||
|
);
|
||||||
|
- private final Map<ResourceLocation, AttributeModifier> modifierById = new Object2ObjectArrayMap<>();
|
||||||
|
- private final Map<ResourceLocation, AttributeModifier> permanentModifiers = new Object2ObjectArrayMap<>();
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ private final Map<ResourceLocation, AttributeModifier> modifierById;
|
||||||
|
+ {
|
||||||
|
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
||||||
|
+ modifierById = it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
|
||||||
|
+ } else {
|
||||||
|
+ modifierById = new Object2ObjectArrayMap<>();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ private final Map<ResourceLocation, AttributeModifier> permanentModifiers;
|
||||||
|
+ {
|
||||||
|
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
||||||
|
+ permanentModifiers = it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
|
||||||
|
+ } else {
|
||||||
|
+ permanentModifiers = new Object2ObjectArrayMap<>();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
private double baseValue;
|
||||||
|
private boolean dirty = true;
|
||||||
|
private double cachedValue;
|
||||||
|
@@ -56,7 +72,13 @@ public class AttributeInstance {
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Map<ResourceLocation, AttributeModifier> getModifiers(AttributeModifier.Operation operation) {
|
||||||
|
- return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> new Object2ObjectOpenHashMap<>());
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ return this.modifiersByOperation.computeIfAbsent(operation, operation1 -> {
|
||||||
|
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled)
|
||||||
|
+ return it.unimi.dsi.fastutil.objects.Object2ObjectMaps.synchronize(new Object2ObjectArrayMap<>(), this);
|
||||||
|
+ else return new Object2ObjectArrayMap<>();
|
||||||
|
+ });
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<AttributeModifier> getModifiers() {
|
||||||
|
@@ -144,8 +166,12 @@ public class AttributeInstance {
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
if (this.dirty) {
|
||||||
|
- this.cachedValue = this.calculateValue();
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ double value = this.calculateValue();
|
||||||
|
+ this.cachedValue = value;
|
||||||
|
this.dirty = false;
|
||||||
|
+ return value;
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.cachedValue;
|
||||||
|
@@ -192,7 +218,15 @@ public class AttributeInstance {
|
||||||
|
compoundTag.store("id", TYPE_CODEC, this.attribute);
|
||||||
|
compoundTag.putDouble("base", this.baseValue);
|
||||||
|
if (!this.permanentModifiers.isEmpty()) {
|
||||||
|
- compoundTag.store("modifiers", AttributeModifier.CODEC.listOf(), List.copyOf(this.permanentModifiers.values()));
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
|
||||||
|
+ synchronized (this) {
|
||||||
|
+ compoundTag.store("modifiers", AttributeModifier.CODEC.listOf(), List.copyOf(this.permanentModifiers.values()));
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ compoundTag.store("modifiers", AttributeModifier.CODEC.listOf(), List.copyOf(this.permanentModifiers.values()));
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
return compoundTag;
|
||||||
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
|
index 701025715e0aca3c1f920a66f9b3d03ec08eaf02..778872cdd1717f1ad52de32faf43847a08c55269 100644
|
||||||
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||||
|
@@ -15,12 +15,14 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public class AttributeMap {
|
||||||
|
// Gale start - Lithium - replace AI attributes with optimized collections
|
||||||
|
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
||||||
|
- private final Set<AttributeInstance> attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||||
|
- private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap();
|
||||||
|
+ private final org.dreeam.leaf.util.map.AttributeInstanceSet attributesToSync = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
|
||||||
|
+ private final org.dreeam.leaf.util.map.AttributeInstanceSet attributesToUpdate = new org.dreeam.leaf.util.map.AttributeInstanceSet((org.dreeam.leaf.util.map.AttributeInstanceArrayMap) attributes);
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
// Gale end - Lithium - replace AI attributes with optimized collections
|
||||||
|
private final AttributeSupplier supplier;
|
||||||
|
- private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations
|
||||||
|
+ //private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
||||||
|
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
|
||||||
|
|
||||||
|
public AttributeMap(AttributeSupplier supplier) {
|
||||||
|
@@ -31,31 +33,54 @@ public class AttributeMap {
|
||||||
|
this.entity = entity;
|
||||||
|
// Purpur end - Ridables
|
||||||
|
this.supplier = defaultAttributes;
|
||||||
|
- this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations
|
||||||
|
+ //this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
- private void onAttributeModified(AttributeInstance instance) {
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ private synchronized void onAttributeModified(AttributeInstance instance) {
|
||||||
|
this.attributesToUpdate.add(instance);
|
||||||
|
if (instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))) { // Purpur - Ridables
|
||||||
|
this.attributesToSync.add(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- public Set<AttributeInstance> getAttributesToSync() {
|
||||||
|
- return this.attributesToSync;
|
||||||
|
+ private static final AttributeInstance[] EMPTY_ATTRIBUTE_INSTANCE = new AttributeInstance[0];
|
||||||
|
+ public synchronized Set<AttributeInstance> getAttributesToSync() {
|
||||||
|
+ var clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToSync.toArray(EMPTY_ATTRIBUTE_INSTANCE));
|
||||||
|
+ this.attributesToSync.clear();
|
||||||
|
+ return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
- public Set<AttributeInstance> getAttributesToUpdate() {
|
||||||
|
- return this.attributesToUpdate;
|
||||||
|
+ public synchronized Set<AttributeInstance> getAttributesToUpdate() {
|
||||||
|
+ var clone = it.unimi.dsi.fastutil.objects.ReferenceArraySet.ofUnchecked(attributesToUpdate.toArray(EMPTY_ATTRIBUTE_INSTANCE));
|
||||||
|
+ this.attributesToUpdate.clear();
|
||||||
|
+ return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public synchronized int[] getAttributesToUpdateIds() {
|
||||||
|
+ int[] clone = attributesToUpdate.inner.toIntArray();
|
||||||
|
+ this.attributesToUpdate.clear();
|
||||||
|
+ return clone;
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
+
|
||||||
|
public Collection<AttributeInstance> getSyncableAttributes() {
|
||||||
|
return this.attributes.values().stream().filter(instance -> instance.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(instance.getAttribute().value()))).collect(Collectors.toList()); // Purpur - Ridables
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public AttributeInstance getInstance(Holder<Attribute> attribute) {
|
||||||
|
- return this.attributes.computeIfAbsent(attribute, this.createInstance); // Gale - Airplane - reduce entity allocations - cache lambda, as for some reason java allocates it anyways
|
||||||
|
+ // Leaf start - Multithreaded tracker
|
||||||
|
+ AttributeInstance v;
|
||||||
|
+ if ((v = this.attributes.get(attribute)) == null) {
|
||||||
|
+ AttributeInstance newValue;
|
||||||
|
+ if ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
|
||||||
|
+ attributes.put(attribute, newValue);
|
||||||
|
+ return newValue;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return v;
|
||||||
|
+ // Leaf end - Multithreaded tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAttribute(Holder<Attribute> attribute) {
|
||||||
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
||||||
|
index 24710041ccbc70e5506d8d89ae34f0141977f209..05de8a77b389691dd6986f36b4cb8cc0935e21e4 100644
|
||||||
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
||||||
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
||||||
|
@@ -11,7 +11,7 @@ public class AttributeSupplier {
|
||||||
|
private final Map<Holder<Attribute>, AttributeInstance> instances;
|
||||||
|
|
||||||
|
AttributeSupplier(Map<Holder<Attribute>, AttributeInstance> instances) {
|
||||||
|
- this.instances = instances;
|
||||||
|
+ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - Optimize AttributeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributeInstance getAttributeInstance(Holder<Attribute> attribute) {
|
||||||
|
@@ -41,7 +41,7 @@ public class AttributeSupplier {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
- public AttributeInstance createInstance(Consumer<AttributeInstance> onDirty, Holder<Attribute> attribute) {
|
||||||
|
+ public AttributeInstance createInstance(Consumer<AttributeInstance> onDirty, Holder<Attribute> attribute) { // Leaf - Multithreaded tracker
|
||||||
|
AttributeInstance attributeInstance = this.instances.get(attribute);
|
||||||
|
if (attributeInstance == null) {
|
||||||
|
return null;
|
||||||
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
|
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
|
||||||
index 36e3937c9e09852937c94c268c877a15337835c5..8aedc3ca463745fe32cac977208b23dc0b8e73b6 100644
|
index 36e3937c9e09852937c94c268c877a15337835c5..8aedc3ca463745fe32cac977208b23dc0b8e73b6 100644
|
||||||
--- a/net/minecraft/world/entity/item/PrimedTnt.java
|
--- a/net/minecraft/world/entity/item/PrimedTnt.java
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ This patch didn't cahce SectionPos or BlockPos to chunkKey, since it needs to co
|
|||||||
TODO: Cache block pos and section pos, whether need?
|
TODO: Cache block pos and section pos, whether need?
|
||||||
|
|
||||||
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..288a3eb57f3431dd624ad8a4b08684563abbc5ad 100644
|
index 4200d22606c6a3dbdf282792a4007a51df66963b..4b258f048c73107d0d050a9aa4b4a39788145b17 100644
|
||||||
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
|
||||||
@@ -127,7 +127,7 @@ public final class NearbyPlayers {
|
@@ -136,7 +136,7 @@ public final class NearbyPlayers {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackedChunk getChunk(final ChunkPos pos) {
|
public TrackedChunk getChunk(final ChunkPos pos) {
|
||||||
@@ -21,7 +21,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..288a3eb57f3431dd624ad8a4b0868456
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TrackedChunk getChunk(final BlockPos pos) {
|
public TrackedChunk getChunk(final BlockPos pos) {
|
||||||
@@ -143,7 +143,7 @@ public final class NearbyPlayers {
|
@@ -152,7 +152,7 @@ public final class NearbyPlayers {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {
|
public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {
|
||||||
@@ -97,7 +97,7 @@ index fd3d0f6cb53bc8b6186f0d86575f21007b2c20ed..cddeeab73e7b981701a42c5aad6b4777
|
|||||||
// Paper end - rewrite chunk system
|
// Paper end - rewrite chunk system
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 7b85a9ebdbe3e8bee0a8fc100ede8a3f07eee5ce..c8c99323b6397c3e595e7a9007e5d801ee2ac14a 100644
|
index 0471b04833fbca5dfc0cc6575692cdefb83edbed..1f3020f5a051d5f4e5c8fa088f844962c3105573 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -503,7 +503,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -503,7 +503,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
|||||||
@@ -8,11 +8,26 @@ Paper: ~75ms
|
|||||||
Leaf: ~48ms (-36%)
|
Leaf: ~48ms (-36%)
|
||||||
This should help drastically on the farms that use actively changing fluids.
|
This should help drastically on the farms that use actively changing fluids.
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
index c6eb136e8db0aa232681ac9bd28c4b70fbbacb40..706e198631e4a3b0a5d2fc3f58060e4a15701ecd 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
@@ -1300,6 +1300,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
this.emptyTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaf start - Use BFS on getSlopeDistance
|
||||||
|
+ public it.unimi.dsi.fastutil.longs.LongSet slopeDistanceCacheVisited = new it.unimi.dsi.fastutil.longs.LongOpenHashSet(512);
|
||||||
|
+ public net.minecraft.world.level.material.FlowingFluid.SlopeDistanceNodeDeque slopeDistanceCacheQueue = new net.minecraft.world.level.material.FlowingFluid.SlopeDistanceNodeDeque();
|
||||||
|
+ // Leaf end - Use BFS on getSlopeDistance
|
||||||
|
private void tickFluid(BlockPos pos, Fluid fluid) {
|
||||||
|
BlockState blockState = this.getBlockState(pos);
|
||||||
|
FluidState fluidState = blockState.getFluidState();
|
||||||
diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java
|
diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java
|
||||||
index 4625bd55e1cb01dfb9921dcd033f05b4a8f9ad74..c0f78556d112e59333ace60f1522e7fd1efe71c3 100644
|
index 4625bd55e1cb01dfb9921dcd033f05b4a8f9ad74..a1c6a30c1e446955b409d1f00c602db06c1e9813 100644
|
||||||
--- a/net/minecraft/world/level/material/FlowingFluid.java
|
--- a/net/minecraft/world/level/material/FlowingFluid.java
|
||||||
+++ b/net/minecraft/world/level/material/FlowingFluid.java
|
+++ b/net/minecraft/world/level/material/FlowingFluid.java
|
||||||
@@ -342,32 +342,81 @@ public abstract class FlowingFluid extends Fluid {
|
@@ -342,32 +342,124 @@ public abstract class FlowingFluid extends Fluid {
|
||||||
|
|
||||||
protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state);
|
protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state);
|
||||||
|
|
||||||
@@ -20,13 +35,15 @@ index 4625bd55e1cb01dfb9921dcd033f05b4a8f9ad74..c0f78556d112e59333ace60f1522e7fd
|
|||||||
- int i = 1000;
|
- int i = 1000;
|
||||||
+ // Leaf start - Use BFS on getSlopeDistance
|
+ // Leaf start - Use BFS on getSlopeDistance
|
||||||
+ protected int getSlopeDistance(LevelReader level, BlockPos startPos, int initialDepth, Direction excludedDirection, BlockState startState, FlowingFluid.SpreadContext spreadContext) {
|
+ protected int getSlopeDistance(LevelReader level, BlockPos startPos, int initialDepth, Direction excludedDirection, BlockState startState, FlowingFluid.SpreadContext spreadContext) {
|
||||||
+ it.unimi.dsi.fastutil.longs.LongSet visited = new it.unimi.dsi.fastutil.longs.LongOpenHashSet(512);
|
+ it.unimi.dsi.fastutil.longs.LongSet visited = ((ServerLevel) level).slopeDistanceCacheVisited;
|
||||||
+ java.util.Queue<FlowingFluid.SlopeDistanceNode> queue = new java.util.ArrayDeque<>(256);
|
+ SlopeDistanceNodeDeque queue = ((ServerLevel) level).slopeDistanceCacheQueue;
|
||||||
|
+ visited.clear();
|
||||||
|
+ queue.clear();
|
||||||
+
|
+
|
||||||
+ for (Direction dir : Direction.Plane.HORIZONTAL) {
|
+ for (Direction dir : Direction.Plane.HORIZONTAL) {
|
||||||
+ if (dir == excludedDirection) continue;
|
+ if (dir == excludedDirection) continue;
|
||||||
+
|
+
|
||||||
+ BlockPos neighborPos = startPos.relative(dir);
|
+ BlockPos neighborPos = startPos.relative(dir); // immutable
|
||||||
+ BlockState neighborState = spreadContext.getBlockStateIfLoaded(neighborPos);
|
+ BlockState neighborState = spreadContext.getBlockStateIfLoaded(neighborPos);
|
||||||
+ if (neighborState == null) continue;
|
+ if (neighborState == null) continue;
|
||||||
+
|
+
|
||||||
@@ -72,7 +89,7 @@ index 4625bd55e1cb01dfb9921dcd033f05b4a8f9ad74..c0f78556d112e59333ace60f1522e7fd
|
|||||||
+ for (Direction dir : Direction.Plane.HORIZONTAL) {
|
+ for (Direction dir : Direction.Plane.HORIZONTAL) {
|
||||||
+ if (dir == current.excludedDir) continue;
|
+ if (dir == current.excludedDir) continue;
|
||||||
+
|
+
|
||||||
+ BlockPos nextPos = current.pos.relative(dir);
|
+ BlockPos nextPos = current.pos.relative(dir); // immutable
|
||||||
+ BlockState nextState = spreadContext.getBlockStateIfLoaded(nextPos);
|
+ BlockState nextState = spreadContext.getBlockStateIfLoaded(nextPos);
|
||||||
+ if (nextState == null) continue;
|
+ if (nextState == null) continue;
|
||||||
+
|
+
|
||||||
@@ -96,18 +113,59 @@ index 4625bd55e1cb01dfb9921dcd033f05b4a8f9ad74..c0f78556d112e59333ace60f1522e7fd
|
|||||||
+ return ((long) pos.getX() & 0xFFFFFFFFL) << 32 | ((long) pos.getZ() & 0xFFFFFFFFL) << 4 | (excludedDir.ordinal() & 0x0F);
|
+ return ((long) pos.getX() & 0xFFFFFFFFL) << 32 | ((long) pos.getZ() & 0xFFFFFFFFL) << 4 | (excludedDir.ordinal() & 0x0F);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ private static class SlopeDistanceNode {
|
+ public static class SlopeDistanceNodeDeque {
|
||||||
+ final BlockPos pos;
|
+ private SlopeDistanceNode[] array;
|
||||||
+ final int depth;
|
+ private int length;
|
||||||
+ final Direction excludedDir;
|
+ private int start;
|
||||||
+ final BlockState state;
|
+ private int end;
|
||||||
+
|
+
|
||||||
+ SlopeDistanceNode(BlockPos pos, int depth, Direction excludedDir, BlockState state) {
|
+ public SlopeDistanceNodeDeque() {
|
||||||
+ this.pos = pos.immutable();
|
+ array = new SlopeDistanceNode[256];
|
||||||
+ this.depth = depth;
|
+ length = array.length;
|
||||||
+ this.excludedDir = excludedDir;
|
|
||||||
+ this.state = state;
|
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ private int size() {
|
||||||
|
+ int apparent = end - start;
|
||||||
|
+ return apparent >= 0 ? apparent : length + apparent;
|
||||||
|
+ }
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ private void clear() {
|
||||||
|
+ start = 0;
|
||||||
|
+ end = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private boolean isEmpty() {
|
||||||
|
+ return end == start || (end <= start && length == start - end);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private SlopeDistanceNode poll() {
|
||||||
|
+ final SlopeDistanceNode t = array[start];
|
||||||
|
+ if (++start == length) start = 0;
|
||||||
|
+ return t;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void add(final SlopeDistanceNode node) {
|
||||||
|
+ array[end++] = node;
|
||||||
|
+ if (end == length) end = 0;
|
||||||
|
+ if (end == start) resize(length, 2 * length);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void resize(final int size, final int newLength) {
|
||||||
|
+ final SlopeDistanceNode[] newArray = new SlopeDistanceNode[newLength];
|
||||||
|
+ if (size != 0) {
|
||||||
|
+ System.arraycopy(array, start, newArray, 0, length - start);
|
||||||
|
+ System.arraycopy(array, 0, newArray, length - start, end);
|
||||||
|
+ }
|
||||||
|
+ start = 0;
|
||||||
|
+ end = size;
|
||||||
|
+ array = newArray;
|
||||||
|
+ length = newLength;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private record SlopeDistanceNode(BlockPos pos, int depth, Direction excludedDir, BlockState state) {
|
||||||
}
|
}
|
||||||
+ // Leaf end - Use BFS on getSlopeDistance
|
+ // Leaf end - Use BFS on getSlopeDistance
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Optimize addOrUpdateTransientModifier
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
index 3ac9f36eae87369354e992a1d9b5c5b2d87d17cb..c39654d3e1e5573646b3729502e4eae1a6dba7c9 100644
|
index 9f09d78a7dac12c7f1b06029d32ad93fae0c2aec..2af5cd6f2b9541cb28075fda014350235a4f72c7 100644
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||||
@@ -87,8 +87,13 @@ public class AttributeInstance {
|
@@ -109,8 +109,13 @@ public class AttributeInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOrUpdateTransientModifier(AttributeModifier modifier) {
|
public void addOrUpdateTransientModifier(AttributeModifier modifier) {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ index 54910c2e1d6e6bb556e536fda060bd09402e04e8..747eb54f84650a9a507398e3d5352e00
|
|||||||
|
|
||||||
// Gale start - Pufferfish - SIMD support
|
// Gale start - Pufferfish - SIMD support
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 1346cff0018e6d17cb892892c3aeebfb86453b60..a753481afe02a2367c378c7f39206fde23eda00d 100644
|
index 1d2c27a7595701895aa3c96339814fd1454a50dd..db3bff36c812a00fc35ebcc6ac6d11ce24040003 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -173,7 +173,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -173,7 +173,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -220,7 +220,7 @@ index 1346cff0018e6d17cb892892c3aeebfb86453b60..a753481afe02a2367c378c7f39206fde
|
|||||||
}
|
}
|
||||||
// Paper - rewrite chunk system
|
// Paper - rewrite chunk system
|
||||||
}
|
}
|
||||||
@@ -1312,6 +1337,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1316,6 +1341,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
}
|
}
|
||||||
// Paper end - rewrite chunk system
|
// Paper end - rewrite chunk system
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ index 1346cff0018e6d17cb892892c3aeebfb86453b60..a753481afe02a2367c378c7f39206fde
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tickBlock(BlockPos pos, Block block) {
|
private void tickBlock(BlockPos pos, Block block) {
|
||||||
@@ -1325,6 +1351,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1329,6 +1355,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
}
|
}
|
||||||
// Paper end - rewrite chunk system
|
// Paper end - rewrite chunk system
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ index 78aee57ad8224b0728411c699d2e3844847c9c79..8f5b400bdf5c1c194f75ee98e2f1e984
|
|||||||
this.tickables.get(i).run();
|
this.tickables.get(i).run();
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||||
index 867936866d952c559b6ffa49fdf78acd70a9bab9..b1953701583ba88c524368a52988fea6fb1ab8d2 100644
|
index 16b2ca8c96e9561aa57e0903d1e98e6441044b6d..939400c18eb4e87e0bf1b131e1601f4dcaa4885c 100644
|
||||||
--- a/net/minecraft/server/level/ServerEntity.java
|
--- a/net/minecraft/server/level/ServerEntity.java
|
||||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||||
@@ -298,6 +298,7 @@ public class ServerEntity {
|
@@ -297,6 +297,7 @@ public class ServerEntity {
|
||||||
this.entity.hurtMarked = false;
|
this.entity.hurtMarked = false;
|
||||||
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: hayanesuru <hayanesuru@outlook.jp>
|
|
||||||
Date: Thu, 15 May 2025 21:11:18 +0900
|
|
||||||
Subject: [PATCH] Optimize AttributeMap
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/Attribute.java b/net/minecraft/world/entity/ai/attributes/Attribute.java
|
|
||||||
index f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b161647497f99b 100644
|
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/Attribute.java
|
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/Attribute.java
|
|
||||||
@@ -16,10 +16,15 @@ public class Attribute {
|
|
||||||
private boolean syncable;
|
|
||||||
private final String descriptionId;
|
|
||||||
private Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE;
|
|
||||||
+ // Leaf start - Optimize AttributeMap
|
|
||||||
+ public final int uid;
|
|
||||||
+ private static final java.util.concurrent.atomic.AtomicInteger SIZE = new java.util.concurrent.atomic.AtomicInteger();
|
|
||||||
+ // Leaf end - Optimize AttributeMap
|
|
||||||
|
|
||||||
protected Attribute(String descriptionId, double defaultValue) {
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.descriptionId = descriptionId;
|
|
||||||
+ this.uid = SIZE.getAndAdd(1); // Leaf - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDefaultValue() {
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
index 701025715e0aca3c1f920a66f9b3d03ec08eaf02..1ef934b02bd99c0fe997e9ec163457b39dba55f0 100644
|
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
||||||
@@ -15,12 +15,12 @@ import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
public class AttributeMap {
|
|
||||||
// Gale start - Lithium - replace AI attributes with optimized collections
|
|
||||||
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
|
||||||
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(); // Leaf - Optimize AttributeMap
|
|
||||||
private final Set<AttributeInstance> attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
|
||||||
private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
|
||||||
// Gale end - Lithium - replace AI attributes with optimized collections
|
|
||||||
private final AttributeSupplier supplier;
|
|
||||||
- private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations
|
|
||||||
+ //private final java.util.function.Function<Holder<Attribute>, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
|
||||||
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
|
|
||||||
|
|
||||||
public AttributeMap(AttributeSupplier supplier) {
|
|
||||||
@@ -31,7 +31,7 @@ public class AttributeMap {
|
|
||||||
this.entity = entity;
|
|
||||||
// Purpur end - Ridables
|
|
||||||
this.supplier = defaultAttributes;
|
|
||||||
- this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations
|
|
||||||
+ //this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onAttributeModified(AttributeInstance instance) {
|
|
||||||
@@ -55,7 +55,17 @@ public class AttributeMap {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public AttributeInstance getInstance(Holder<Attribute> attribute) {
|
|
||||||
- return this.attributes.computeIfAbsent(attribute, this.createInstance); // Gale - Airplane - reduce entity allocations - cache lambda, as for some reason java allocates it anyways
|
|
||||||
+ // Leaf start - Optimize AttributeMap
|
|
||||||
+ AttributeInstance v;
|
|
||||||
+ if ((v = this.attributes.get(attribute)) == null) {
|
|
||||||
+ AttributeInstance newValue;
|
|
||||||
+ if ((newValue = this.supplier.createInstance(this::onAttributeModified, attribute)) != null) {
|
|
||||||
+ this.attributes.put(attribute, newValue);
|
|
||||||
+ return newValue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return v;
|
|
||||||
+ // Leaf end - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasAttribute(Holder<Attribute> attribute) {
|
|
||||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
|
||||||
index 24710041ccbc70e5506d8d89ae34f0141977f209..09341ef6c651150aba223689badbead490162b2b 100644
|
|
||||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
|
||||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java
|
|
||||||
@@ -11,7 +11,7 @@ public class AttributeSupplier {
|
|
||||||
private final Map<Holder<Attribute>, AttributeInstance> instances;
|
|
||||||
|
|
||||||
AttributeSupplier(Map<Holder<Attribute>, AttributeInstance> instances) {
|
|
||||||
- this.instances = instances;
|
|
||||||
+ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - Optimize AttributeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
public AttributeInstance getAttributeInstance(Holder<Attribute> attribute) {
|
|
||||||
@@ -94,10 +94,10 @@ index 0f9d18dd29e210ad656da211a3cb1cb25cd4efb1..d1c36cd17c83e7e0167046093c4a2b84
|
|||||||
|
|
||||||
for (LevelChunk levelChunk : list) {
|
for (LevelChunk levelChunk : list) {
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index a753481afe02a2367c378c7f39206fde23eda00d..753b4255d9e9b9628bc5825a6b4f0f2540f06e7a 100644
|
index db3bff36c812a00fc35ebcc6ac6d11ce24040003..e8706189de80a2f0e60882fff0fe891165050f38 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -1367,13 +1367,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1371,13 +1371,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
// Paper end - log detailed entity tick information
|
// Paper end - log detailed entity tick information
|
||||||
|
|
||||||
public void tickNonPassenger(Entity entity) {
|
public void tickNonPassenger(Entity entity) {
|
||||||
@@ -111,7 +111,7 @@ index a753481afe02a2367c378c7f39206fde23eda00d..753b4255d9e9b9628bc5825a6b4f0f25
|
|||||||
entity.setOldPosAndRot();
|
entity.setOldPosAndRot();
|
||||||
entity.tickCount++;
|
entity.tickCount++;
|
||||||
entity.totalEntityAge++; // Paper - age-like counter for all entities
|
entity.totalEntityAge++; // Paper - age-like counter for all entities
|
||||||
@@ -1386,13 +1380,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -1390,13 +1384,6 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
for (Entity entity1 : entity.getPassengers()) {
|
for (Entity entity1 : entity.getPassengers()) {
|
||||||
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
|
this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
|
||||||
}
|
}
|
||||||
@@ -4,18 +4,18 @@ Date: Fri, 23 May 2025 12:01:42 +0900
|
|||||||
Subject: [PATCH] Cache block path type
|
Subject: [PATCH] Cache block path type
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/Bootstrap.java b/net/minecraft/server/Bootstrap.java
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
index 83bc2f6b7774c8753a15dbeb00f0c9103713fd1b..20a720253092b4ec0b648edf06a048f92da201e0 100644
|
index 595284787053a5fb7385e8493953c73a19fe7aee..6dec45b376288638433f0d50e474f9713266d99c 100644
|
||||||
--- a/net/minecraft/server/Bootstrap.java
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
+++ b/net/minecraft/server/Bootstrap.java
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
@@ -60,6 +60,7 @@ public class Bootstrap {
|
@@ -360,6 +360,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||||
io.papermc.paper.world.worldgen.OptionallyFlatBedrockConditionSource.bootstrap(); // Paper - Flat bedrock generator settings
|
}
|
||||||
});
|
|
||||||
// Paper end
|
if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) mobSpawnExecutor.start(); // Pufferfish
|
||||||
+ net.minecraft.world.level.block.Blocks.initPathType(); // Leaf - Cache path type
|
+ net.minecraft.world.level.block.Blocks.initPathType(); // Leaf - Cache path type
|
||||||
CreativeModeTabs.validate();
|
org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur - Implement TPSBar
|
||||||
wrapStreams();
|
if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur - Give bee counts in beehives to Purpur clients
|
||||||
bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis());
|
|
||||||
diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java
|
diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java
|
||||||
index 303bd27d44e4acfee49334235a6704724e3fd616..d001d0859c9508eb06f05010ab1cb8069f9b87cf 100644
|
index 303bd27d44e4acfee49334235a6704724e3fd616..d001d0859c9508eb06f05010ab1cb8069f9b87cf 100644
|
||||||
--- a/net/minecraft/world/level/block/Blocks.java
|
--- a/net/minecraft/world/level/block/Blocks.java
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||||
|
Date: Sat, 17 Feb 2024 17:57:08 -0500
|
||||||
|
Subject: [PATCH] Rail Optimization: optimized PoweredRailBlock logic
|
||||||
|
|
||||||
|
Original project: https://github.com/FxMorin/RailOptimization
|
||||||
|
|
||||||
|
Full Rewrite of the powered rail iteration logic
|
||||||
|
that makes powered/activator rails turning on/off up to 4x faster.
|
||||||
|
This rewrite brings a massive performance boost while keeping the vanilla order. This is achieved by running all the
|
||||||
|
powered rail logic from a single rail instead of each block iterating separately. Which was not only very
|
||||||
|
expensive but also completely unnecessary and with a lot of massive overhead
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/block/PoweredRailBlock.java b/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
|
index a2202d2b4352be07b2445064339c61ba6a2521c7..abf0ffa3540963f591f428876c0c671517594c89 100644
|
||||||
|
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
|
||||||
|
@@ -122,6 +122,12 @@ public class PoweredRailBlock extends BaseRailBlock {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateState(BlockState state, Level level, BlockPos pos, Block block) {
|
||||||
|
+ // Leaf start - Rail Optimization
|
||||||
|
+ if (org.dreeam.leaf.config.modules.opt.OptimizedPoweredRails.enabled) {
|
||||||
|
+ org.dreeam.leaf.world.block.OptimizedPoweredRails.updateState(this, state, level, pos);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Rail Optimization
|
||||||
|
boolean poweredValue = state.getValue(POWERED);
|
||||||
|
boolean flag = level.hasNeighborSignal(pos)
|
||||||
|
|| this.findPoweredRailSignal(level, pos, state, true, 0)
|
||||||
@@ -71,8 +71,21 @@ index 2a63e8e725fa97da5d4b9fba6bfe19377c7cfbe1..0c286eabd8e4d5e599d93a151874af6b
|
|||||||
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
|
set.add(connection.getPlayer().getBukkitEntity().getPlayer());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
index cab15624afaeaca5d69206a0b7fff5da54e5ef29..4533fbbbc35ed92177f7704f243a1614a1773ca1 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
@@ -2892,7 +2892,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
Iterator<AttributeInstance> iterator = collection.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
AttributeInstance genericInstance = iterator.next();
|
||||||
|
- if (genericInstance.getAttribute() == Attributes.MAX_HEALTH) {
|
||||||
|
+ if (genericInstance != null && genericInstance.getAttribute() == Attributes.MAX_HEALTH) { // Leaf - Multithreaded tracker
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
index 3a3fbbfa0b82092cd9ac8eab2d179fb9f590aec8..566eab1add471266c8617747c8c25ee04e13c02f 100644
|
index 5300a513a295d472752d31a6e8af48bb64b06704..fec0f3b72c1808c5019e95760e3fef19c45e1be0 100644
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||||
@@ -1751,6 +1751,26 @@ public class CraftEventFactory {
|
@@ -1751,6 +1751,26 @@ public class CraftEventFactory {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||||
|
Date: Thu, 24 Apr 2025 16:36:16 -0400
|
||||||
|
Subject: [PATCH] Paw optimization
|
||||||
|
|
||||||
|
Some random optimizations
|
||||||
|
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||||
|
index 34a2e07dabc546799df6881de30252397d856f05..d8aca1d7ffad3eccaae676263a41a9a1f04988b9 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
|
||||||
|
@@ -244,13 +244,37 @@ public class CraftBlockData implements BlockData {
|
||||||
|
|
||||||
|
if (!states.isEmpty()) {
|
||||||
|
stateString.append('[');
|
||||||
|
- stateString.append(states.entrySet().stream().map(StateHolder.PROPERTY_ENTRY_TO_STRING_FUNCTION).collect(Collectors.joining(",")));
|
||||||
|
+ // Leaf start - paw optimization
|
||||||
|
+ int i = 0;
|
||||||
|
+ for (Map.Entry<Property<?>, Comparable<?>> propertyEntry : states.entrySet()) {
|
||||||
|
+ if (propertyEntry == null) {
|
||||||
|
+ stateString.append("<NULL>");
|
||||||
|
+ } else {
|
||||||
|
+ Property<?> property = propertyEntry.getKey();
|
||||||
|
+ Comparable<?> value = propertyEntry.getValue();
|
||||||
|
+
|
||||||
|
+ stateString.append(property.getName()).append("=").append(getValueName(property, value));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (i < states.size() - 1) {
|
||||||
|
+ stateString.append(",");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ i++;
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - paw optimization
|
||||||
|
stateString.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaf start - paw optimization
|
||||||
|
+ private <T extends Comparable<T>> String getValueName(Property<T> property, Comparable<?> value) {
|
||||||
|
+ return property.getName((T) value);
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - paw optimization
|
||||||
|
+
|
||||||
|
public Map<String, String> toStates(boolean hideUnspecified) {
|
||||||
|
return (hideUnspecified && this.parsedStates != null) ? CraftBlockData.toStates(this.parsedStates) : CraftBlockData.toStates(this.state.getValues());
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Taiyou06 <kaandindar21@gmail.com>
|
||||||
|
Date: Sun, 1 Jun 2025 18:13:24 +0200
|
||||||
|
Subject: [PATCH] optimise ReferenceList
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java
|
||||||
|
index 8df9406b77eb3c225ebf88bf76a7adb666452f3b..14ac2a533e0b882f26ee4a11f8d6bccfe752c750 100644
|
||||||
|
--- a/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java
|
||||||
|
+++ b/src/main/java/ca/spottedleaf/moonrise/common/list/ReferenceList.java
|
||||||
|
@@ -47,17 +47,21 @@ public final class ReferenceList<E> implements Iterable<E> {
|
||||||
|
|
||||||
|
// move the object at the end to this index
|
||||||
|
final int endIndex = --this.count;
|
||||||
|
- final E end = (E)this.references[endIndex];
|
||||||
|
if (index != endIndex) {
|
||||||
|
+ // The removed element was not the last one.
|
||||||
|
+ // Move the element that was at 'endIndex' (the old tail) to 'index'.
|
||||||
|
+ final E end = (E)this.references[endIndex];
|
||||||
|
// not empty after this call
|
||||||
|
this.referenceToIndex.put(end, index); // update index
|
||||||
|
+ this.references[index] = end;
|
||||||
|
}
|
||||||
|
- this.references[index] = end;
|
||||||
|
+ // Null out the slot at 'endIndex'.
|
||||||
|
+ // If 'index == endIndex', this was the slot of the removed element.
|
||||||
|
+ // If 'index != endIndex', this was the original slot of the moved element 'end'.
|
||||||
|
this.references[endIndex] = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
public boolean add(final E obj) {
|
||||||
|
final int count = this.count;
|
||||||
|
final int currIndex = this.referenceToIndex.putIfAbsent(obj, count);
|
||||||
@@ -18,7 +18,6 @@ public class AsyncGoalExecutor {
|
|||||||
protected final SpscIntQueue queue;
|
protected final SpscIntQueue queue;
|
||||||
protected final SpscIntQueue wake;
|
protected final SpscIntQueue wake;
|
||||||
protected final IntArrayList submit;
|
protected final IntArrayList submit;
|
||||||
private final AsyncGoalThread thread;
|
|
||||||
private final ServerLevel world;
|
private final ServerLevel world;
|
||||||
private long midTickCount = 0L;
|
private long midTickCount = 0L;
|
||||||
|
|
||||||
@@ -27,7 +26,6 @@ public class AsyncGoalExecutor {
|
|||||||
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
this.queue = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
||||||
this.wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
this.wake = new SpscIntQueue(AsyncTargetFinding.queueSize);
|
||||||
this.submit = new IntArrayList();
|
this.submit = new IntArrayList();
|
||||||
this.thread = thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean wake(int id) {
|
boolean wake(int id) {
|
||||||
@@ -46,7 +44,18 @@ public class AsyncGoalExecutor {
|
|||||||
|
|
||||||
public final void tick() {
|
public final void tick() {
|
||||||
batchSubmit();
|
batchSubmit();
|
||||||
LockSupport.unpark(thread);
|
while (true) {
|
||||||
|
OptionalInt result = this.wake.recv();
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int id = result.getAsInt();
|
||||||
|
if (poll(id) && !this.queue.send(id)) {
|
||||||
|
do {
|
||||||
|
wake(id);
|
||||||
|
} while (poll(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void batchSubmit() {
|
private void batchSubmit() {
|
||||||
@@ -67,18 +76,6 @@ public class AsyncGoalExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void midTick() {
|
public final void midTick() {
|
||||||
while (true) {
|
|
||||||
OptionalInt result = this.wake.recv();
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int id = result.getAsInt();
|
|
||||||
if (poll(id) && !this.queue.send(id)) {
|
|
||||||
do {
|
|
||||||
wake(id);
|
|
||||||
} while (poll(id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (AsyncTargetFinding.threshold <= 0L || (midTickCount % AsyncTargetFinding.threshold) == 0L) {
|
if (AsyncTargetFinding.threshold <= 0L || (midTickCount % AsyncTargetFinding.threshold) == 0L) {
|
||||||
batchSubmit();
|
batchSubmit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.dreeam.leaf.async.chunk;
|
package org.dreeam.leaf.async.chunk;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -14,13 +15,13 @@ public class AsyncChunkSend {
|
|||||||
public static final ExecutorService POOL = new ThreadPoolExecutor(
|
public static final ExecutorService POOL = new ThreadPoolExecutor(
|
||||||
1, 1, 0L, TimeUnit.MILLISECONDS,
|
1, 1, 0L, TimeUnit.MILLISECONDS,
|
||||||
new LinkedBlockingQueue<>(),
|
new LinkedBlockingQueue<>(),
|
||||||
new com.google.common.util.concurrent.ThreadFactoryBuilder()
|
new ThreadFactoryBuilder()
|
||||||
.setPriority(Thread.NORM_PRIORITY - 2)
|
.setPriority(Thread.NORM_PRIORITY)
|
||||||
.setNameFormat("Leaf Async Chunk Send Thread")
|
.setNameFormat("Leaf Async Chunk Send Thread")
|
||||||
.setUncaughtExceptionHandler(Util::onThreadException)
|
.setUncaughtExceptionHandler(Util::onThreadException)
|
||||||
.setThreadFactory(AsyncChunkSendThread::new)
|
.setThreadFactory(AsyncChunkSendThread::new)
|
||||||
.build(),
|
.build(),
|
||||||
new ThreadPoolExecutor.DiscardPolicy()
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||||
);
|
);
|
||||||
public static final Logger LOGGER = LogManager.getLogger("Leaf Async Chunk Send");
|
public static final Logger LOGGER = LogManager.getLogger("Leaf Async Chunk Send");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.minecraft.server.MinecraftServer;
|
|||||||
import net.minecraft.world.level.pathfinder.Path;
|
import net.minecraft.world.level.pathfinder.Path;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dreeam.leaf.config.modules.async.AsyncPathfinding;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -29,8 +30,8 @@ public class AsyncPathProcessor {
|
|||||||
private static long lastWarnMillis = System.currentTimeMillis();
|
private static long lastWarnMillis = System.currentTimeMillis();
|
||||||
private static final ThreadPoolExecutor pathProcessingExecutor = new ThreadPoolExecutor(
|
private static final ThreadPoolExecutor pathProcessingExecutor = new ThreadPoolExecutor(
|
||||||
1,
|
1,
|
||||||
org.dreeam.leaf.config.modules.async.AsyncPathfinding.asyncPathfindingMaxThreads,
|
AsyncPathfinding.asyncPathfindingMaxThreads,
|
||||||
org.dreeam.leaf.config.modules.async.AsyncPathfinding.asyncPathfindingKeepalive, TimeUnit.SECONDS,
|
AsyncPathfinding.asyncPathfindingKeepalive, TimeUnit.SECONDS,
|
||||||
getQueueImpl(),
|
getQueueImpl(),
|
||||||
new ThreadFactoryBuilder()
|
new ThreadFactoryBuilder()
|
||||||
.setNameFormat(THREAD_PREFIX + " Thread - %d")
|
.setNameFormat(THREAD_PREFIX + " Thread - %d")
|
||||||
@@ -44,7 +45,7 @@ public class AsyncPathProcessor {
|
|||||||
public void rejectedExecution(Runnable rejectedTask, ThreadPoolExecutor executor) {
|
public void rejectedExecution(Runnable rejectedTask, ThreadPoolExecutor executor) {
|
||||||
BlockingQueue<Runnable> workQueue = executor.getQueue();
|
BlockingQueue<Runnable> workQueue = executor.getQueue();
|
||||||
if (!executor.isShutdown()) {
|
if (!executor.isShutdown()) {
|
||||||
switch (org.dreeam.leaf.config.modules.async.AsyncPathfinding.asyncPathfindingRejectPolicy) {
|
switch (AsyncPathfinding.asyncPathfindingRejectPolicy) {
|
||||||
case FLUSH_ALL -> {
|
case FLUSH_ALL -> {
|
||||||
if (!workQueue.isEmpty()) {
|
if (!workQueue.isEmpty()) {
|
||||||
List<Runnable> pendingTasks = new ArrayList<>(workQueue.size());
|
List<Runnable> pendingTasks = new ArrayList<>(workQueue.size());
|
||||||
@@ -98,7 +99,7 @@ public class AsyncPathProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static BlockingQueue<Runnable> getQueueImpl() {
|
private static BlockingQueue<Runnable> getQueueImpl() {
|
||||||
final int queueCapacity = org.dreeam.leaf.config.modules.async.AsyncPathfinding.asyncPathfindingQueueSize;
|
final int queueCapacity = AsyncPathfinding.asyncPathfindingQueueSize;
|
||||||
|
|
||||||
return new LinkedBlockingQueue<>(queueCapacity);
|
return new LinkedBlockingQueue<>(queueCapacity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,15 +32,6 @@ public class MultithreadedTracker {
|
|||||||
private static long lastWarnMillis = System.currentTimeMillis();
|
private static long lastWarnMillis = System.currentTimeMillis();
|
||||||
private static ThreadPoolExecutor TRACKER_EXECUTOR = null;
|
private static ThreadPoolExecutor TRACKER_EXECUTOR = null;
|
||||||
|
|
||||||
private record SendChanges(Object[] entities, int size) implements Runnable {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
((ServerEntity) entities[i]).sendDirtyEntityData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MultithreadedTracker() {
|
private MultithreadedTracker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +71,6 @@ public class MultithreadedTracker {
|
|||||||
|
|
||||||
// Move tracking to off-main
|
// Move tracking to off-main
|
||||||
TRACKER_EXECUTOR.execute(() -> {
|
TRACKER_EXECUTOR.execute(() -> {
|
||||||
ReferenceArrayList<ServerEntity> sendDirty = new ReferenceArrayList<>();
|
|
||||||
for (final Entity entity : trackerEntitiesRaw) {
|
for (final Entity entity : trackerEntitiesRaw) {
|
||||||
if (entity == null) continue;
|
if (entity == null) continue;
|
||||||
|
|
||||||
@@ -88,19 +78,12 @@ public class MultithreadedTracker {
|
|||||||
|
|
||||||
if (tracker == null) continue;
|
if (tracker == null) continue;
|
||||||
|
|
||||||
// Don't Parallel Tick Tracker of Entity
|
synchronized (tracker) {
|
||||||
synchronized (tracker.sync) {
|
var trackedChunk = nearbyPlayers.getChunk(entity.chunkPosition());
|
||||||
tracker.moonrise$tick(nearbyPlayers.getChunk(entity.chunkPosition()));
|
tracker.moonrise$tick(trackedChunk);
|
||||||
tracker.serverEntity.sendChanges();
|
tracker.serverEntity.sendChanges();
|
||||||
if (tracker.serverEntity.wantSendDirtyEntityData) {
|
|
||||||
tracker.serverEntity.wantSendDirtyEntityData = false;
|
|
||||||
sendDirty.add(tracker.serverEntity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!sendDirty.isEmpty()) {
|
|
||||||
level.getServer().execute(new SendChanges(sendDirty.elements(), sendDirty.size()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +104,7 @@ public class MultithreadedTracker {
|
|||||||
|
|
||||||
if (tracker == null) continue;
|
if (tracker == null) continue;
|
||||||
|
|
||||||
synchronized (tracker.sync) {
|
synchronized (tracker) {
|
||||||
tickTask[index] = tracker.leafTickCompact(nearbyPlayers.getChunk(entity.chunkPosition()));
|
tickTask[index] = tracker.leafTickCompact(nearbyPlayers.getChunk(entity.chunkPosition()));
|
||||||
sendChangesTasks[index] = () -> tracker.serverEntity.sendChanges(); // Collect send changes to task array
|
sendChangesTasks[index] = () -> tracker.serverEntity.sendChanges(); // Collect send changes to task array
|
||||||
}
|
}
|
||||||
@@ -140,22 +123,6 @@ public class MultithreadedTracker {
|
|||||||
|
|
||||||
sendChanges.run();
|
sendChanges.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReferenceArrayList<ServerEntity> sendDirty = new ReferenceArrayList<>();
|
|
||||||
for (final Entity entity : trackerEntitiesRaw) {
|
|
||||||
if (entity == null) continue;
|
|
||||||
|
|
||||||
final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity();
|
|
||||||
|
|
||||||
if (tracker == null) continue;
|
|
||||||
if (tracker.serverEntity.wantSendDirtyEntityData) {
|
|
||||||
tracker.serverEntity.wantSendDirtyEntityData = false;
|
|
||||||
sendDirty.add(tracker.serverEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!sendDirty.isEmpty()) {
|
|
||||||
level.getServer().execute(new SendChanges(sendDirty.elements(), sendDirty.size()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,8 +227,12 @@ public class LeafConfig {
|
|||||||
extraConfigs.addAll(Arrays.asList(existing.split(",")));
|
extraConfigs.addAll(Arrays.asList(existing.split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use same way in spark's BukkitServerConfigProvider#getNestedFiles to get all world configs
|
||||||
|
// It may spam in the spark profiler, but it's ok, since spark uses YamlConfigParser.INSTANCE to
|
||||||
|
// get configs defined in extra config flag instead of using SplitYamlConfigParser.INSTANCE
|
||||||
for (World world : Bukkit.getWorlds()) {
|
for (World world : Bukkit.getWorlds()) {
|
||||||
extraConfigs.add(world.getWorldFolder().getName() + "/gale-world.yml"); // Gale world config
|
Path galeWorldFolder = world.getWorldFolder().toPath().resolve("gale-world.yml");
|
||||||
|
extraConfigs.add(galeWorldFolder.toString().replace("\\", "/").replace("./", "")); // Gale world config
|
||||||
}
|
}
|
||||||
|
|
||||||
return extraConfigs;
|
return extraConfigs;
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ import org.dreeam.leaf.config.annotations.Experimental;
|
|||||||
public class SparklyPaperParallelWorldTicking extends ConfigModules {
|
public class SparklyPaperParallelWorldTicking extends ConfigModules {
|
||||||
|
|
||||||
public String getBasePath() {
|
public String getBasePath() {
|
||||||
return EnumConfigCategory.ASYNC.getBaseKeyName() + ".parallel-world-tracking";
|
return EnumConfigCategory.ASYNC.getBaseKeyName() + ".parallel-world-ticking";
|
||||||
} // TODO: Correct config key when stable
|
}
|
||||||
|
|
||||||
@Experimental
|
@Experimental
|
||||||
public static boolean enabled = false;
|
public static boolean enabled = false;
|
||||||
public static int threads = 8;
|
public static int threads = 8;
|
||||||
public static boolean logContainerCreationStacktraces = false;
|
public static boolean logContainerCreationStacktraces = false;
|
||||||
public static boolean disableHardThrow = false;
|
public static boolean disableHardThrow = false;
|
||||||
|
@Deprecated
|
||||||
public static boolean runAsyncTasksSync = false;
|
public static boolean runAsyncTasksSync = false;
|
||||||
|
// STRICT, BUFFERED, DISABLED
|
||||||
|
public static String asyncUnsafeReadHandling = "BUFFERED";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaded() {
|
public void onLoaded() {
|
||||||
@@ -34,15 +37,30 @@ public class SparklyPaperParallelWorldTicking extends ConfigModules {
|
|||||||
} else {
|
} else {
|
||||||
threads = 0;
|
threads = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
logContainerCreationStacktraces = config.getBoolean(getBasePath() + ".log-container-creation-stacktraces", logContainerCreationStacktraces);
|
logContainerCreationStacktraces = config.getBoolean(getBasePath() + ".log-container-creation-stacktraces", logContainerCreationStacktraces);
|
||||||
logContainerCreationStacktraces = enabled && logContainerCreationStacktraces;
|
logContainerCreationStacktraces = enabled && logContainerCreationStacktraces;
|
||||||
disableHardThrow = config.getBoolean(getBasePath() + ".disable-hard-throw", disableHardThrow);
|
disableHardThrow = config.getBoolean(getBasePath() + ".disable-hard-throw", disableHardThrow);
|
||||||
disableHardThrow = enabled && disableHardThrow;
|
disableHardThrow = enabled && disableHardThrow;
|
||||||
runAsyncTasksSync = config.getBoolean(getBasePath() + ".run-async-tasks-sync", runAsyncTasksSync);
|
asyncUnsafeReadHandling = config.getString(getBasePath() + ".async-unsafe-read-handling", asyncUnsafeReadHandling).toUpperCase();
|
||||||
runAsyncTasksSync = enabled && runAsyncTasksSync;
|
|
||||||
|
if (!asyncUnsafeReadHandling.equals("STRICT") && !asyncUnsafeReadHandling.equals("BUFFERED") && !asyncUnsafeReadHandling.equals("DISABLED")) {
|
||||||
|
LeafConfig.LOGGER.warn("Invalid value for {}.async-unsafe-read-handling: {}, fallback to STRICT.", getBasePath(), asyncUnsafeReadHandling);
|
||||||
|
asyncUnsafeReadHandling = "STRICT";
|
||||||
|
}
|
||||||
|
if (!enabled) {
|
||||||
|
asyncUnsafeReadHandling = "DISABLED";
|
||||||
|
}
|
||||||
|
|
||||||
|
runAsyncTasksSync = config.getBoolean(getBasePath() + ".run-async-tasks-sync", false); // Default to false now
|
||||||
|
if (runAsyncTasksSync) {
|
||||||
|
LeafConfig.LOGGER.warn("The setting '{}.run-async-tasks-sync' is deprecated. Use 'async-unsafe-read-handling: STRICT' for similar safety checks or 'BUFFERED' for buffered reads.", getBasePath());
|
||||||
|
}
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
LeafConfig.LOGGER.info("Using {} threads for Parallel World Ticking", threads);
|
LeafConfig.LOGGER.info("Using {} threads for Parallel World Ticking", threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runAsyncTasksSync = enabled && runAsyncTasksSync; // Auto-disable if main feature is off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.dreeam.leaf.config.modules.opt;
|
||||||
|
|
||||||
|
import org.dreeam.leaf.config.ConfigModules;
|
||||||
|
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||||
|
|
||||||
|
public class OptimizedPoweredRails extends ConfigModules {
|
||||||
|
|
||||||
|
public String getBasePath() {
|
||||||
|
return EnumConfigCategory.PERF.getBaseKeyName() + ".optimized-powered-rails";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enabled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaded() {
|
||||||
|
enabled = config().getBoolean(getBasePath(), enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import java.util.*;
|
|||||||
import java.util.AbstractMap.SimpleEntry;
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
|
|
||||||
// fast array backend map with O(1) get & put & remove
|
// fast array backend map with O(1) get & put & remove
|
||||||
public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, AttributeInstance>, Cloneable {
|
public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, AttributeInstance>, Cloneable {
|
||||||
|
|
||||||
private int size = 0;
|
private int size = 0;
|
||||||
private transient AttributeInstance[] a = new AttributeInstance[32];
|
private transient AttributeInstance[] a = new AttributeInstance[32];
|
||||||
@@ -46,17 +46,17 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int size() {
|
public int size() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return size == 0;
|
return size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean containsKey(Object key) {
|
public boolean containsKey(Object key) {
|
||||||
if (key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute) {
|
if (key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute) {
|
||||||
int uid = attribute.uid;
|
int uid = attribute.uid;
|
||||||
return uid >= 0 && uid < a.length && a[uid] != null;
|
return uid >= 0 && uid < a.length && a[uid] != null;
|
||||||
@@ -65,22 +65,22 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
for (final AttributeInstance instance : a) {
|
return value instanceof AttributeInstance val && Objects.equals(getInstance(val.getAttribute().value().uid), val);
|
||||||
if (Objects.equals(value, instance)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance get(Object key) {
|
public AttributeInstance get(Object key) {
|
||||||
return key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute ? a[attribute.uid] : null;
|
return key instanceof Holder<?> holder && holder.value() instanceof Attribute attribute ? a[attribute.uid] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public AttributeInstance getInstance(int key) {
|
||||||
|
return a[key];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance put(@NotNull Holder<Attribute> key, AttributeInstance value) {
|
public AttributeInstance put(@NotNull Holder<Attribute> key, AttributeInstance value) {
|
||||||
int uid = key.value().uid;
|
int uid = key.value().uid;
|
||||||
AttributeInstance prev = a[uid];
|
AttributeInstance prev = a[uid];
|
||||||
setByIndex(uid, value);
|
setByIndex(uid, value);
|
||||||
@@ -88,7 +88,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final AttributeInstance remove(Object key) {
|
public AttributeInstance remove(Object key) {
|
||||||
if (!(key instanceof Holder<?> holder) || !(holder.value() instanceof Attribute attribute)) return null;
|
if (!(key instanceof Holder<?> holder) || !(holder.value() instanceof Attribute attribute)) return null;
|
||||||
int uid = attribute.uid;
|
int uid = attribute.uid;
|
||||||
AttributeInstance prev = a[uid];
|
AttributeInstance prev = a[uid];
|
||||||
@@ -97,7 +97,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void putAll(@NotNull Map<? extends Holder<Attribute>, ? extends AttributeInstance> m) {
|
public void putAll(@NotNull Map<? extends Holder<Attribute>, ? extends AttributeInstance> m) {
|
||||||
for (AttributeInstance e : m.values()) {
|
for (AttributeInstance e : m.values()) {
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
setByIndex(e.getAttribute().value().uid, e);
|
setByIndex(e.getAttribute().value().uid, e);
|
||||||
@@ -106,13 +106,13 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void clear() {
|
public void clear() {
|
||||||
Arrays.fill(a, null);
|
Arrays.fill(a, null);
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Set<Holder<Attribute>> keySet() {
|
public @NotNull Set<Holder<Attribute>> keySet() {
|
||||||
if (keys == null) {
|
if (keys == null) {
|
||||||
keys = new KeySet();
|
keys = new KeySet();
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Collection<AttributeInstance> values() {
|
public @NotNull Collection<AttributeInstance> values() {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
values = new Values();
|
values = new Values();
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final @NotNull Set<Entry<Holder<Attribute>, AttributeInstance>> entrySet() {
|
public @NotNull Set<Entry<Holder<Attribute>, AttributeInstance>> entrySet() {
|
||||||
if (entries == null) {
|
if (entries == null) {
|
||||||
entries = new EntrySet();
|
entries = new EntrySet();
|
||||||
}
|
}
|
||||||
@@ -136,13 +136,23 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof AttributeInstanceArrayMap that)) return false;
|
if (o == this) return true;
|
||||||
return size == that.size && Arrays.equals(a, that.a);
|
if (!(o instanceof Map<?, ?> s)) return false;
|
||||||
|
if (s.size() != size()) return false;
|
||||||
|
if (o instanceof AttributeInstanceArrayMap that) {
|
||||||
|
return Arrays.equals(a, that.a);
|
||||||
|
}
|
||||||
|
for (Entry<?, ?> e : s.entrySet()) {
|
||||||
|
if (!Objects.equals(get(e.getKey()), e.getValue())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public int hashCode() {
|
||||||
return Arrays.hashCode(a);
|
return Arrays.hashCode(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +202,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
if (!hasNext()) throw new NoSuchElementException();
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
currentIndex = nextIndex;
|
currentIndex = nextIndex;
|
||||||
nextIndex = findNextOccupied(nextIndex + 1);
|
nextIndex = findNextOccupied(nextIndex + 1);
|
||||||
return BuiltInRegistries.ATTRIBUTE.asHolderIdMap().byIdOrThrow(currentIndex);
|
return BuiltInRegistries.ATTRIBUTE.get(currentIndex).orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -279,7 +289,7 @@ public class AttributeInstanceArrayMap implements Map<Holder<Attribute>, Attribu
|
|||||||
public Entry<Holder<Attribute>, AttributeInstance> next() {
|
public Entry<Holder<Attribute>, AttributeInstance> next() {
|
||||||
if (!hasNext()) throw new NoSuchElementException();
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
currentIndex = nextIndex;
|
currentIndex = nextIndex;
|
||||||
Holder<Attribute> key = BuiltInRegistries.ATTRIBUTE.asHolderIdMap().byIdOrThrow(nextIndex);
|
Holder<Attribute> key = BuiltInRegistries.ATTRIBUTE.get(nextIndex).orElseThrow();
|
||||||
AttributeInstance value = a[nextIndex];
|
AttributeInstance value = a[nextIndex];
|
||||||
nextIndex = findNextOccupied(nextIndex + 1);
|
nextIndex = findNextOccupied(nextIndex + 1);
|
||||||
return new SimpleEntry<>(key, value) {
|
return new SimpleEntry<>(key, value) {
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package org.dreeam.leaf.util.map;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public final class AttributeInstanceSet extends AbstractCollection<AttributeInstance> implements Set<AttributeInstance> {
|
||||||
|
public final IntSet inner;
|
||||||
|
public final AttributeInstanceArrayMap map;
|
||||||
|
|
||||||
|
public AttributeInstanceSet(AttributeInstanceArrayMap map) {
|
||||||
|
this.map = map;
|
||||||
|
inner = new IntArraySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(AttributeInstance instance) {
|
||||||
|
return inner.add(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return o instanceof AttributeInstance instance && inner.remove(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Iterator<AttributeInstance> iterator() {
|
||||||
|
return new CloneIterator(inner.toIntArray(), map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return inner.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return inner.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
inner.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
if (o instanceof AttributeInstance instance) {
|
||||||
|
return inner.contains(instance.getAttribute().value().uid);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeInstance @NotNull [] toArray() {
|
||||||
|
int[] innerClone = inner.toIntArray();
|
||||||
|
AttributeInstance[] arr = new AttributeInstance[innerClone.length];
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] = map.getInstance(innerClone[i]);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
@Override
|
||||||
|
public <T> T @NotNull [] toArray(T[] a) {
|
||||||
|
if (a == null || (a.getClass() == AttributeInstance[].class && a.length == 0)) {
|
||||||
|
return (T[]) toArray();
|
||||||
|
}
|
||||||
|
if (a.length < size()) {
|
||||||
|
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size());
|
||||||
|
}
|
||||||
|
System.arraycopy((T[]) toArray(), 0, a, 0, size());
|
||||||
|
if (a.length > size()) {
|
||||||
|
a[size()] = null;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CloneIterator implements Iterator<AttributeInstance> {
|
||||||
|
private final int[] array;
|
||||||
|
private int index = 0;
|
||||||
|
private final AttributeInstanceArrayMap map;
|
||||||
|
|
||||||
|
CloneIterator(int[] array, AttributeInstanceArrayMap map) {
|
||||||
|
this.array = array;
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < array.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeInstance next() {
|
||||||
|
if (!hasNext()) throw new NoSuchElementException();
|
||||||
|
return map.getInstance(array[index++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) return true;
|
||||||
|
if (!(o instanceof Set<?> s)) return false;
|
||||||
|
if (s.size() != size()) return false;
|
||||||
|
return containsAll(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.dreeam.leaf.util.biome;
|
package org.dreeam.leaf.world.biome;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
@@ -0,0 +1,333 @@
|
|||||||
|
package org.dreeam.leaf.world.block;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.PoweredRailBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.RailShape;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import static net.minecraft.world.level.block.Block.*;
|
||||||
|
import static net.minecraft.world.level.block.PoweredRailBlock.POWERED;
|
||||||
|
import static net.minecraft.world.level.block.PoweredRailBlock.SHAPE;
|
||||||
|
|
||||||
|
public class OptimizedPoweredRails {
|
||||||
|
|
||||||
|
private static final Direction[] EAST_WEST_DIR = new Direction[]{Direction.WEST, Direction.EAST};
|
||||||
|
private static final Direction[] NORTH_SOUTH_DIR = new Direction[]{Direction.SOUTH, Direction.NORTH};
|
||||||
|
|
||||||
|
private static final int UPDATE_FORCE_PLACE = UPDATE_MOVE_BY_PISTON | UPDATE_KNOWN_SHAPE | UPDATE_CLIENTS;
|
||||||
|
|
||||||
|
private static int RAIL_POWER_LIMIT = 8;
|
||||||
|
|
||||||
|
private static void giveShapeUpdate(Level level, BlockState state, BlockPos pos, BlockPos fromPos, Direction direction) {
|
||||||
|
BlockState oldState = level.getBlockState(pos);
|
||||||
|
Block.updateOrDestroy(
|
||||||
|
oldState,
|
||||||
|
oldState.updateShape(level, level, pos, direction.getOpposite(), fromPos, state, level.random),
|
||||||
|
level,
|
||||||
|
pos,
|
||||||
|
UPDATE_CLIENTS & -34,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getRailPowerLimit() {
|
||||||
|
return RAIL_POWER_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRailPowerLimit(int powerLimit) {
|
||||||
|
RAIL_POWER_LIMIT = powerLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateState(PoweredRailBlock self, BlockState state, Level level, BlockPos pos) {
|
||||||
|
boolean shouldBePowered = level.hasNeighborSignal(pos) ||
|
||||||
|
self.findPoweredRailSignal(level, pos, state, true, 0) ||
|
||||||
|
self.findPoweredRailSignal(level, pos, state, false, 0);
|
||||||
|
if (shouldBePowered != state.getValue(POWERED)) {
|
||||||
|
RailShape railShape = state.getValue(SHAPE);
|
||||||
|
if (railShape.isSlope()) {
|
||||||
|
level.setBlock(pos, state.setValue(POWERED, shouldBePowered), 3);
|
||||||
|
level.updateNeighborsAtExceptFromFacing(pos.below(), self, Direction.UP, null);
|
||||||
|
level.updateNeighborsAtExceptFromFacing(pos.above(), self, Direction.DOWN, null); // isSlope
|
||||||
|
} else if (shouldBePowered) {
|
||||||
|
powerLane(self, level, pos, state, railShape);
|
||||||
|
} else {
|
||||||
|
dePowerLane(self, level, pos, state, railShape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
boolean bl, int distance, RailShape shape,
|
||||||
|
HashMap<BlockPos, Boolean> checkedPos) {
|
||||||
|
BlockState blockState = world.getBlockState(pos);
|
||||||
|
boolean speedCheck = checkedPos.containsKey(pos) && checkedPos.get(pos);
|
||||||
|
if (speedCheck) {
|
||||||
|
return world.hasNeighborSignal(pos) ||
|
||||||
|
findPoweredRailSignalFaster(self, world, pos, blockState, bl, distance + 1, checkedPos);
|
||||||
|
} else {
|
||||||
|
if (blockState.is(self)) {
|
||||||
|
RailShape railShape = blockState.getValue(SHAPE);
|
||||||
|
if (shape == RailShape.EAST_WEST && (
|
||||||
|
railShape == RailShape.NORTH_SOUTH ||
|
||||||
|
railShape == RailShape.ASCENDING_NORTH ||
|
||||||
|
railShape == RailShape.ASCENDING_SOUTH
|
||||||
|
) || shape == RailShape.NORTH_SOUTH && (
|
||||||
|
railShape == RailShape.EAST_WEST ||
|
||||||
|
railShape == RailShape.ASCENDING_EAST ||
|
||||||
|
railShape == RailShape.ASCENDING_WEST
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
} else if (blockState.getValue(POWERED)) {
|
||||||
|
return world.hasNeighborSignal(pos) ||
|
||||||
|
findPoweredRailSignalFaster(self, world, pos, blockState, bl, distance + 1, checkedPos);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean findPoweredRailSignalFaster(PoweredRailBlock self, Level level,
|
||||||
|
BlockPos pos, BlockState state, boolean bl, int distance,
|
||||||
|
HashMap<BlockPos, Boolean> checkedPos) {
|
||||||
|
if (distance >= RAIL_POWER_LIMIT - 1) return false;
|
||||||
|
int i = pos.getX();
|
||||||
|
int j = pos.getY();
|
||||||
|
int k = pos.getZ();
|
||||||
|
boolean bl2 = true;
|
||||||
|
RailShape railShape = state.getValue(SHAPE);
|
||||||
|
switch (railShape.ordinal()) {
|
||||||
|
case 0 -> {
|
||||||
|
if (bl) ++k;
|
||||||
|
else --k;
|
||||||
|
}
|
||||||
|
case 1 -> {
|
||||||
|
if (bl) --i;
|
||||||
|
else ++i;
|
||||||
|
}
|
||||||
|
case 2 -> {
|
||||||
|
if (bl) {
|
||||||
|
--i;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
bl2 = false;
|
||||||
|
}
|
||||||
|
railShape = RailShape.EAST_WEST;
|
||||||
|
}
|
||||||
|
case 3 -> {
|
||||||
|
if (bl) {
|
||||||
|
--i;
|
||||||
|
++j;
|
||||||
|
bl2 = false;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
railShape = RailShape.EAST_WEST;
|
||||||
|
}
|
||||||
|
case 4 -> {
|
||||||
|
if (bl) {
|
||||||
|
++k;
|
||||||
|
} else {
|
||||||
|
--k;
|
||||||
|
++j;
|
||||||
|
bl2 = false;
|
||||||
|
}
|
||||||
|
railShape = RailShape.NORTH_SOUTH;
|
||||||
|
}
|
||||||
|
case 5 -> {
|
||||||
|
if (bl) {
|
||||||
|
++k;
|
||||||
|
++j;
|
||||||
|
bl2 = false;
|
||||||
|
} else {
|
||||||
|
--k;
|
||||||
|
}
|
||||||
|
railShape = RailShape.NORTH_SOUTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findPoweredRailSignalFaster(
|
||||||
|
self, level, new BlockPos(i, j, k),
|
||||||
|
bl, distance, railShape, checkedPos
|
||||||
|
) ||
|
||||||
|
(bl2 && findPoweredRailSignalFaster(
|
||||||
|
self, level, new BlockPos(i, j - 1, k),
|
||||||
|
bl, distance, railShape, checkedPos
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void powerLane(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
BlockState mainState, RailShape railShape) {
|
||||||
|
world.setBlock(pos, mainState.setValue(POWERED, true), UPDATE_FORCE_PLACE);
|
||||||
|
HashMap<BlockPos, Boolean> checkedPos = new HashMap<>();
|
||||||
|
checkedPos.put(pos, true);
|
||||||
|
int[] count = new int[2];
|
||||||
|
if (railShape == RailShape.NORTH_SOUTH) { // Order: +z, -z
|
||||||
|
for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
||||||
|
setRailPositionsPower(self, world, pos, checkedPos, count, i, NORTH_SOUTH_DIR[i]);
|
||||||
|
}
|
||||||
|
updateRails(self, false, world, pos, mainState, count);
|
||||||
|
} else if (railShape == RailShape.EAST_WEST) { // Order: -x, +x
|
||||||
|
for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
||||||
|
setRailPositionsPower(self, world, pos, checkedPos, count, i, EAST_WEST_DIR[i]);
|
||||||
|
}
|
||||||
|
updateRails(self, true, world, pos, mainState, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dePowerLane(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
BlockState mainState, RailShape railShape) {
|
||||||
|
world.setBlock(pos, mainState.setValue(POWERED, false), UPDATE_FORCE_PLACE);
|
||||||
|
int[] count = new int[2];
|
||||||
|
if (railShape == RailShape.NORTH_SOUTH) { // Order: +z, -z
|
||||||
|
for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
||||||
|
setRailPositionsDePower(self, world, pos, count, i, NORTH_SOUTH_DIR[i]);
|
||||||
|
}
|
||||||
|
updateRails(self, false, world, pos, mainState, count);
|
||||||
|
} else if (railShape == RailShape.EAST_WEST) { // Order: -x, +x
|
||||||
|
for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
||||||
|
setRailPositionsDePower(self, world, pos, count, i, EAST_WEST_DIR[i]);
|
||||||
|
}
|
||||||
|
updateRails(self, true, world, pos, mainState, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setRailPositionsPower(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
HashMap<BlockPos, Boolean> checkedPos, int[] count, int i, Direction dir) {
|
||||||
|
for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
||||||
|
BlockPos newPos = pos.relative(dir, z);
|
||||||
|
BlockState state = world.getBlockState(newPos);
|
||||||
|
if (checkedPos.containsKey(newPos)) {
|
||||||
|
if (!checkedPos.get(newPos)) break;
|
||||||
|
count[i]++;
|
||||||
|
} else if (!state.is(self) || state.getValue(POWERED) || !(
|
||||||
|
world.hasNeighborSignal(newPos) ||
|
||||||
|
findPoweredRailSignalFaster(self, world, newPos, state, true, 0, checkedPos) ||
|
||||||
|
findPoweredRailSignalFaster(self, world, newPos, state, false, 0, checkedPos)
|
||||||
|
)) {
|
||||||
|
checkedPos.put(newPos, false);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
checkedPos.put(newPos, true);
|
||||||
|
world.setBlock(newPos, state.setValue(POWERED, true), UPDATE_FORCE_PLACE);
|
||||||
|
count[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setRailPositionsDePower(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
int[] count, int i, Direction dir) {
|
||||||
|
for (int z = 1; z < RAIL_POWER_LIMIT; z++) {
|
||||||
|
BlockPos newPos = pos.relative(dir, z);
|
||||||
|
BlockState state = world.getBlockState(newPos);
|
||||||
|
if (!state.is(self) || !state.getValue(POWERED) || world.hasNeighborSignal(newPos) ||
|
||||||
|
self.findPoweredRailSignal(world, newPos, state, true, 0) ||
|
||||||
|
self.findPoweredRailSignal(world, newPos, state, false, 0)) break;
|
||||||
|
world.setBlock(newPos, state.setValue(POWERED, false), UPDATE_FORCE_PLACE);
|
||||||
|
count[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void shapeUpdateEnd(PoweredRailBlock self, Level world, BlockPos pos, BlockState mainState,
|
||||||
|
int endPos, Direction direction, int currentPos, BlockPos blockPos) {
|
||||||
|
if (currentPos == endPos) {
|
||||||
|
BlockPos newPos = pos.relative(direction, currentPos + 1);
|
||||||
|
giveShapeUpdate(world, mainState, newPos, pos, direction);
|
||||||
|
BlockState state = world.getBlockState(blockPos);
|
||||||
|
if (state.is(self) && state.getValue(SHAPE).isSlope()) giveShapeUpdate(world, mainState, newPos.above(), pos, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void neighborUpdateEnd(PoweredRailBlock self, Level world, BlockPos pos, int endPos,
|
||||||
|
Direction direction, Block block, int currentPos, BlockPos blockPos) {
|
||||||
|
if (currentPos == endPos) {
|
||||||
|
BlockPos newPos = pos.relative(direction, currentPos + 1);
|
||||||
|
world.neighborChanged(newPos, block, null);
|
||||||
|
BlockState state = world.getBlockState(blockPos);
|
||||||
|
if (state.is(self) && state.getValue(SHAPE).isSlope()) world.neighborChanged(newPos.above(), block, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateRailsSectionEastWestShape(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
int c, BlockState mainState, Direction dir,
|
||||||
|
int[] count, int countAmt) {
|
||||||
|
BlockPos pos1 = pos.relative(dir, c);
|
||||||
|
if (c == 0 && count[1] == 0) giveShapeUpdate(world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite());
|
||||||
|
shapeUpdateEnd(self, world, pos, mainState, countAmt, dir, c, pos1);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.north(), pos, Direction.NORTH);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.south(), pos, Direction.SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateRailsSectionNorthSouthShape(PoweredRailBlock self, Level world, BlockPos pos,
|
||||||
|
int c, BlockState mainState, Direction dir,
|
||||||
|
int[] count, int countAmt) {
|
||||||
|
BlockPos pos1 = pos.relative(dir, c);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.west(), pos, Direction.WEST);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.east(), pos, Direction.EAST);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN);
|
||||||
|
giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP);
|
||||||
|
shapeUpdateEnd(self, world, pos, mainState, countAmt, dir, c, pos1);
|
||||||
|
if (c == 0 && count[1] == 0) giveShapeUpdate(world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateRails(PoweredRailBlock self, boolean eastWest, Level world,
|
||||||
|
BlockPos pos, BlockState mainState, int[] count) {
|
||||||
|
if (eastWest) {
|
||||||
|
for (int i = 0; i < EAST_WEST_DIR.length; ++i) {
|
||||||
|
int countAmt = count[i];
|
||||||
|
if (i == 1 && countAmt == 0) continue;
|
||||||
|
Direction dir = EAST_WEST_DIR[i];
|
||||||
|
Block block = mainState.getBlock();
|
||||||
|
for (int c = countAmt; c >= i; c--) {
|
||||||
|
BlockPos p = pos.relative(dir, c);
|
||||||
|
if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, null);
|
||||||
|
neighborUpdateEnd(self, world, pos, countAmt, dir, block, c, p);
|
||||||
|
world.neighborChanged(p.below(), block, null);
|
||||||
|
world.neighborChanged(p.above(), block, null);
|
||||||
|
world.neighborChanged(p.north(), block, null);
|
||||||
|
world.neighborChanged(p.south(), block, null);
|
||||||
|
BlockPos pos2 = pos.relative(dir, c).below();
|
||||||
|
world.neighborChanged(pos2.below(), block, null);
|
||||||
|
world.neighborChanged(pos2.north(), block, null);
|
||||||
|
world.neighborChanged(pos2.south(), block, null);
|
||||||
|
if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, null);
|
||||||
|
if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()).below(), block, null);
|
||||||
|
}
|
||||||
|
for (int c = countAmt; c >= i; c--)
|
||||||
|
updateRailsSectionEastWestShape(self, world, pos, c, mainState, dir, count, countAmt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) {
|
||||||
|
int countAmt = count[i];
|
||||||
|
if (i == 1 && countAmt == 0) continue;
|
||||||
|
Direction dir = NORTH_SOUTH_DIR[i];
|
||||||
|
Block block = mainState.getBlock();
|
||||||
|
for (int c = countAmt; c >= i; c--) {
|
||||||
|
BlockPos p = pos.relative(dir, c);
|
||||||
|
world.neighborChanged(p.west(), block, null);
|
||||||
|
world.neighborChanged(p.east(), block, null);
|
||||||
|
world.neighborChanged(p.below(), block, null);
|
||||||
|
world.neighborChanged(p.above(), block, null);
|
||||||
|
neighborUpdateEnd(self, world, pos, countAmt, dir, block, c, p);
|
||||||
|
if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, null);
|
||||||
|
BlockPos pos2 = pos.relative(dir, c).below();
|
||||||
|
world.neighborChanged(pos2.west(), block, null);
|
||||||
|
world.neighborChanged(pos2.east(), block, null);
|
||||||
|
world.neighborChanged(pos2.below(), block, null);
|
||||||
|
if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, null);
|
||||||
|
if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()).below(), block, null);
|
||||||
|
}
|
||||||
|
for (int c = countAmt; c >= i; c--)
|
||||||
|
updateRailsSectionNorthSouthShape(self, world, pos, c, mainState, dir, count, countAmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
todos.md
2
todos.md
@@ -13,4 +13,4 @@
|
|||||||
- [ ] Check Purpur's Projectile offset config, in BowItem shoot
|
- [ ] Check Purpur's Projectile offset config, in BowItem shoot
|
||||||
- [ ] Remove Gale's attribute patch
|
- [ ] Remove Gale's attribute patch
|
||||||
- [ ] Check SparklyPaper's mapitem update skip
|
- [ ] Check SparklyPaper's mapitem update skip
|
||||||
- [ ] Update from Leaf 1.21.4 (curr commit: `a022d84c5b5b52f7e8a62f6bff774d0c23176ed5`)
|
- [ ] Update from Leaf 1.21.4 (curr commit: `12711630d4ca8788366f8abd47275c4c262ff13f`)
|
||||||
|
|||||||
Reference in New Issue
Block a user