Compare commits

...

19 Commits

Author SHA1 Message Date
Helvetica Volubi 4df4d07ae9 Merge the duplicate configuration items (#151)
* do not release & push repo before finished

* langs update

* updateSuppression config moved up

* redirect tick command option to carpet config system

* optimizedDragonRespawn

* diff in files

* counter rules transformed

* oops!

* some fakeplayer options moved up

* simplify

* creative no clip moved

* pre remove core module

* pre update luminol to further fix a bug that config not saved to real file

* fix up transform

* fix up transform

* fix up

* fix up some problem in PR

* redirect forgotten moved config

* fix bugs in PR

* refix

* switch for final merge
2026-06-15 20:27:41 +08:00
Helvetica Volubi cfc73efc9a Update Luminol 2026-06-14 18:43:18 +08:00
Helvetica Volubi 0989bcaec7 [ci skip]refactor: convert AbstractConcurrentTable to interface and update ConcurrentTable implementation 2026-06-13 01:19:56 +08:00
Helvetica Volubi 3763d0b885 Update clip & weight 2026-06-10 03:20:21 +08:00
Roberta001 cd3db4ae8c Fix bot connection region crash (#149)
* Fix: bot connection causing region crash, fix readme

* Fix NPE on Region Shutdown with bots

* simple fix up

* Revert "Fix NPE on Region Shutdown with bots"

This reverts commit b55c982cb9.

* Revert "fix: fix a bug in server shutdown with fakeplayer"

This reverts commit a721c27e96.

* fix: improve bot shutdown handling to prevent region crashes

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
2026-06-09 16:17:13 +08:00
Bacteriawa 11e9760eb3 Add validation and safety checks across protocols
Harden NBT/packet handling and add defensive checks across multiple protocols and utilities.

- ServerBot: Improved create-state NBT parsing, fill legacy fallbacks, validate skin list entries, and guard loading of saved actions/configs with try/catch and logged warnings.
- LeavesProtocolManager: Treat malformed payloads as rejected (INVALID_PAYLOAD), avoid throwing on decode failures, add safe bytebuf invocation with logging, and a selector description helper.
- REIServerProtocol: Enforce tag types and presence, validate indices and slot bounds, and improve error messages for malformed REI data.
- LitematicaSchematic: Validate schematic metadata (non-empty regions, palette), check region sizes and limit volume to a maximum, and avoid silent failures.
- ServuxLitematicsProtocol: Wrap Litematica paste handling in try/catch, notify player on invalid data, and log warnings.
- LitematicaBitArray: Validate array size/backing storage, prevent oversized backing arrays, and add index bounds checks.
- LitematicaBlockStatePalette: Improve error messaging for invalid palette entries.
- SchematicPlacement: Validate required tags (Schematics/Origin/SubRegion positions), use safe enum-by-ordinal lookup, and guard against null vanilla boxes when streaming chunk positions.
- CommunicationManager: Validate ordinals for rotation/mirror, limit sub-region modification counts, and catch/reject malformed Syncmatica packets with logging.

Overall this commit improves robustness by validating inputs, avoiding unhandled runtime exceptions from malformed or malicious data, and adding informative logs for rejected payloads.
2026-06-09 02:24:45 +08:00
Helvetica Volubi 13c5bd7331 Update Luminol to fix endportal teleport problem 2026-06-07 15:36:24 +08:00
Helvetica Volubi bbcc103643 Update Luminol 2026-06-06 22:10:57 +08:00
Helvetica Volubi a721c27e96 fix: fix a bug in server shutdown with fakeplayer 2026-06-06 04:48:38 +08:00
Helvetica Volubi 09011f05e6 Update Luminol 2026-06-05 16:31:04 +08:00
Helvetica Volubi b8692e23d2 [ci skip]remove some import in patches 2026-06-04 14:56:05 +08:00
Helvetica Volubi 1bb1811027 Add trigger command unsafe support 2026-06-04 01:02:14 +08:00
Helvetica Volubi a4936582bb [ci skip] switch to release
because of no code update, we will start release next commit
2026-06-04 00:53:49 +08:00
Helvetica Volubi fc760a047f port: port 1.21.11 changes, fix some bugs in lagFree (https://github.com/LuminolMC/Lophine/issues/145)
Origin Commit: 311fd32acb
2026-06-03 20:19:26 +08:00
Helvetica Volubi 5567b194d7 update file's sign & add update suppression event to Leaves Features Manager 2026-06-03 13:57:27 +08:00
Helvetica Volubi f6f2781237 enabled forgotten config sync 2026-06-03 13:25:28 +08:00
Bacteriawa f469ad848b Add MiniTweaks mob fire/explosion rules
Add a MiniTweaks patch that adjusts mob explosion and fire behavior and expose new config flags.

- Add patch file features/0043-MiniTweaks-mob-fire-and-explosion-rules.patch updating Creeper, LargeFireball and SmallFireball logic to consult config flags when deciding whether explosions break blocks or create fire.
- Add four new config options to GeneralCompatConfig: noCreeperBlockBreaking, noGhastBlockBreaking, disableBlazeFire, disableGhastFire.

These changes allow disabling creeper/ghast block breaking and suppressing blaze/ghast-caused fire while preserving existing explosion event handling.
2026-06-03 13:22:25 +08:00
Bacteriawa 924ab75f1d Remove Carpet features patches and protocols
Delete Carpet integration: remove luminol and minecraft Carpet feature patch files (1todos/server/luminol-patches/features/0006-Carpet-features.patch and 1todos/server/minecraft-patches/features/0044-Carpet-features.patch) and remove related protocol implementations (1todos/server/src/lophine/protocol/CarpetLoggerProtocol.java and 1todos/server/src/lophine/protocol/tiscm/TISCMProtocol.java). These files contained the Carpet feature backport/compat patches and protocol helpers; removing them cleans up the obsolete Carpet-specific changes.
2026-06-03 13:22:25 +08:00
Bacteriawa 1b2f577e42 Add Carpet features, update Leaves patches
Register a new lophine_carpet config and add Carpet feature patches and protocol classes. Adds luminol and minecraft Carpet feature patches, plus CarpetLoggerProtocol and TISCMProtocol Java files. Updates many Leaves-related patch files (metadata and authors/dates) and applies Leaves behaviour changes across numerous block classes (onRemove handling, affectNeighborsAfterRemoval wiring, Containers.dropContentsOnDestroy, etc.) to preserve pre-1.21.1 behaviour and compatibility. These changes enable Carpet integration and ensure Leaves patches are consistently applied across the codebase.
2026-06-03 13:22:24 +08:00
93 changed files with 1675 additions and 1156 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ git clone https://github.com/LuminolMC/Lophine.git
cd Lophine
# 应用补丁并构建 Paperclip JAR
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
./gradlew applyAllPatches && ./gradlew createPaperclipJar
```
构建完成后,您可以在 `lophine-server/build/libs` 目录中找到生成的 JAR 文件。
+1 -1
View File
@@ -45,7 +45,7 @@ git clone https://github.com/LuminolMC/Lophine.git
cd Lophine
# Apply patches and build Paperclip JAR
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
./gradlew applyAllPatches && ./gradlew createPaperclipJar
```
After building, you can find the generated JAR file in the `lophine-server/build/libs` directory.
+5 -5
View File
@@ -1,15 +1,15 @@
group=fun.bm.lophine
mcVersion=26.1.2
apiVersion=26.1.2
channel=BETA
clipVersion=3.0.17
weightVersion=2.0.12
channel=STABLE
clipVersion=3.0.18
weightVersion=2.0.15
# true for release, false for skip release, pre for pre-release
release=pre
release=true
# true for push to repo, false for skip push repo, auto for detect by release value
pushRepo=auto
luminolRef=397a754b718e76edbe1a9d6d583054f885db5fde
luminolRef=6dbf8f3ee48c8fcb791be55706a33a8f29c5a042
org.gradle.configuration-cache=true
org.gradle.caching=true
+1 -1
View File
@@ -50,7 +50,7 @@
+ implementation(project(":lophine-api"))
// Luminol start - Dependenices insert
implementation("net.objecthunter:exp4j:0.4.8")
implementation("com.electronwill.night-config:toml:3.8.3") // Night config
implementation("com.electronwill.night-config:toml:3.9.0") // Night config
@@ -234,14 +_,14 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
@@ -5,14 +5,14 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 490316c7d5cbb77e988039cfa7a7cc0aa3849730..f5fb4e210c07f32e52eb8c1ba166d1571a6778c7 100644
index a2f5a99ee45a0810fd338ccf6f71df3a077ca62b..05e1aa84586284ac0389e7023f975bfb08438535 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -24,6 +24,7 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
preLoad();
}
@@ -5,7 +5,7 @@ Subject: [PATCH] Leaves: Fakeplayer
diff --git a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
index 0a20c6f03625391201e5ced167707e54ed27daa1..2872b22e44cba48442c526f0a53e1fc6c5ce760f 100644
index 0a20c6f03625391201e5ced167707e54ed27daa1..dc983bcb8d2e90ad27a693dfcd6debb4b2c2b86b 100644
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
@@ -46,6 +46,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
@@ -21,23 +21,21 @@ index 0a20c6f03625391201e5ced167707e54ed27daa1..2872b22e44cba48442c526f0a53e1fc6
this.waypoints.add(waypoint);
for (ServerPlayer toCreateFor : this.trackingPlayers) {
@@ -101,7 +107,13 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
@@ -101,6 +107,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
scheduleIfOffTarget(player, () -> {
this.trackingPlayers.add(player);
- for (WaypointTransmitter transmitter : this.waypoints) {
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
+
+ for (WaypointTransmitter transmitter : this.waypoints) {
for (WaypointTransmitter transmitter : this.waypoints) {
this.createConnection(player, transmitter);
}
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
index 8f0548908a9e43ce29c4476f2707f6898e540aec..8b7c66785a06eb4782de0b0a9b542221d6258220 100644
index 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab5822601939 100644
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
@@ -11,14 +11,7 @@ public class ServerFeatureManager implements FeatureManager {
@@ -53,6 +51,6 @@ index 8f0548908a9e43ce29c4476f2707f6898e540aec..8b7c66785a06eb4782de0b0a9b542221
- ));
- }
+ availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
if (Boolean.getBoolean("leavesclip.enable.mixin")) {
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -5,7 +5,7 @@ Subject: [PATCH] Leaves: Replay Mod API
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
index 8b7c66785a06eb4782de0b0a9b542221d6258220..1f3fe7f786bb8f7c59e3a0235dcc572f3171ee6b 100644
index 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c 100644
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
@@ -12,6 +12,7 @@ public class ServerFeatureManager implements FeatureManager {
@@ -13,6 +13,6 @@ index 8b7c66785a06eb4782de0b0a9b542221d6258220..1f3fe7f786bb8f7c59e3a0235dcc572f
private ServerFeatureManager() {
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
if (Boolean.getBoolean("leavesclip.enable.mixin")) {
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 3 Jun 2026 13:49:39 +0800
Subject: [PATCH] Update suppression event
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
index 0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c..c3db6c5281728fa1a2b4d84f9ebff9fcfd696698 100644
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
@@ -13,6 +13,7 @@ public class ServerFeatureManager implements FeatureManager {
private ServerFeatureManager() {
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
+ availableFeatures.add(UPDATE_SUPPRESSION_EVENT); // Lophine - update suppression event support
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -5,14 +5,14 @@ Subject: [PATCH] Carpet features
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index f5fb4e210c07f32e52eb8c1ba166d1571a6778c7..e990c147e1b632ef5a33e4f3c37b5cd608040ac7 100644
index 05e1aa84586284ac0389e7023f975bfb08438535..da9ff49be1c7a12ea93d665c37e828afd24d7070 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -25,6 +25,13 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
+ configfiles.put("lophine_carpet", ConfigsInstance.of(
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
+ registerConfig("lophine_carpet", ConfigsInstance.of(
+ new java.io.File("lophine_config"),
+ "lophine_carpet",
+ "lophine_carpet_config.toml",
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 5 Jun 2026 16:10:25 +0800
Subject: [PATCH] Carpet Features Compatible
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
index f079a1cd99d648dc7ca97fb65406b7a42ad5a74e..30f78cbae7aea3e9fcee6d97f229ddf8e8344299 100644
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
@@ -23,9 +23,4 @@ public class CommandConfig implements IConfigModule {
""")
@HotReloadUnsupported
public static boolean waypointsAndWaypointCommand = false;
- @ConfigInfo(name = "enable_tick_command", comments = """
- Only freeze/unfreeze/step/query command is allowed if you enabled it.
- WARN: This should disabled in production environment!
- """)
- public static boolean tick = false;
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
deleted file mode 100644
index f791feed92abd750ac10775c05150f122ecbe886..0000000000000000000000000000000000000000
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package me.earthme.luminol.config.modules.optimizations;
-
-import me.earthme.luminol.config.IConfigModule;
-import me.earthme.luminol.config.flags.ConfigClassInfo;
-import me.earthme.luminol.config.flags.ConfigInfo;
-import me.earthme.luminol.enums.EnumConfigCategory;
-
-@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "end_dragon")
-public class OptimizedDragonRespawnConfig implements IConfigModule {
- @ConfigInfo(name = "optimized_dragon_respawn")
- public static boolean optimizedRespawn = false;
-}
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 15 Jun 2026 01:33:32 +0800
Subject: [PATCH] TEMP: Temporarily transform config between different config
system
Should be removed in Minecraft 26.2 Update
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index da9ff49be1c7a12ea93d665c37e828afd24d7070..dc6e6d38ebe0c4f7f481da571ab116015fd08cd2 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -62,6 +62,10 @@ public class ConfigManager {
CompletableFuture.allOf(futures).join();
CommandRegister.register(); // register command after config loaded to enable some command didn't depend on config files
initialized = true;
+
+ reApplyStagedConfigs();
+ saveConfigs();
+ configfiles.values().forEach((config) -> config.reload(true, false));
}
public static void registerRunnableBeforeFinalLoad(Runnable runnable) {
@@ -26,10 +26,10 @@ index 49c7f8194be8222e329fc3215a6aa6db0b221b11..c6c968d28e0d14a4c50e66bdd5176a00
loadFromJson(stream, output);
} catch (JsonParseException | IOException var7) {
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
index 5b46b224bb0fea3a7e0f721ce9770657ffe0c71d..44d594da98615a8bbfb2560e0a63d2e7aab3cc7e 100644
index 143ad4e342b184aa02b6fbbe81508e244eebc7a2..89be42b8519522398920eb424c894fd2ab8c9666 100644
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -154,6 +154,8 @@ public class Main {
@@ -155,6 +155,8 @@ public class Main {
return;
}
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix datapack command save function
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 35c1b7f40563823401ca204ec41ef57220b5ad55..f993a4de22558e7b9598aa7500cd3cc1225e4c5b 100644
index 83178b9a0b017c8945c0f41981838f40263c9a12..ef898f5b60219be00471f9ea227103dfcea5b202 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2472,6 +2472,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to disable some check for operators
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index aa9e99358e5f3a5d07d9902708bcfa6255d26b97..47beff71ed33e7fbd6fe6cd47aa955233af41f04 100644
index b2dc29f75259eca66f5dfe4456845b6dd70b0baf..15470867ed0f668fd3ba9c1fa24f84b3de8cb756 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -399,7 +399,7 @@ public class ServerGamePacketListenerImpl
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable save-all command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 3416445888860746c15a978f401c87245609b64a..fc6402dd0a47f5b2792aa8a21703bfee18dd2388 100644
index 11cacb26ce260373476dad764014ba1852477831..981f63b75584dbcb4bb0d5672e8c8bb140c52f9d 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -359,6 +359,8 @@ public final class RegionizedServer {
@@ -364,6 +364,8 @@ public final class RegionizedServer {
// tick player ping sample
this.tickPlayerSample();
@@ -31,10 +31,10 @@ index 02c004bc7f9a0203523ce4b27cd766d6bdc478c0..3d86e21198f2888422330b6f7c27712f
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index bcb1a5ec17269529ef0f9556043a7183df846eab..4503e62a72e67d35db5b091c91e903058157bdbd 100644
index 89f61f5715942d2b521e04b9fdc8b1b379c0c957..2c2487e1c1c65438119a13bd705a9e44697955ed 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -295,7 +295,11 @@ public class Commands {
@@ -299,7 +299,11 @@ public class Commands {
PardonCommand.register(this.dispatcher);
PardonIpCommand.register(this.dispatcher);
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
@@ -48,7 +48,7 @@ index bcb1a5ec17269529ef0f9556043a7183df846eab..4503e62a72e67d35db5b091c91e90305
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f993a4de22558e7b9598aa7500cd3cc1225e4c5b..82315368d5580563fc77548f22a65d04ec73b622 100644
index ef898f5b60219be00471f9ea227103dfcea5b202..4991b8a925d9431d80f42a4480d76d6602a85347 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1683,6 +1683,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 4503e62a72e67d35db5b091c91e903058157bdbd..86866a9fa92d2e1ac0026e5764f459cc73e0b266 100644
index 2c2487e1c1c65438119a13bd705a9e44697955ed..6d27350cdb2e699fcc541bc96a5af06a09e0dfd5 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -217,7 +217,9 @@ public class Commands {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 86866a9fa92d2e1ac0026e5764f459cc73e0b266..f54f6047f326189329e11338b17105f5555dde12 100644
index 6d27350cdb2e699fcc541bc96a5af06a09e0dfd5..01784d3feaa0dce02f0c26b9a635877b735e6abf 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -244,7 +244,11 @@ public class Commands {
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Thu, 4 Jun 2026 00:56:32 +0800
Subject: [PATCH] Add config to enable trigger command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 01784d3feaa0dce02f0c26b9a635877b735e6abf..bb5059a77741bf1d9e73bd8c7f0da6681ec63f67 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -272,7 +272,11 @@ public class Commands {
// Luminol end - Add a config to enable tick command
TimeCommand.register(this.dispatcher, context);
TitleCommand.register(this.dispatcher, context);
- //TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Lophine start - Add a config to enable trigger command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.trigger) {
+ TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Lophine end - Add a config to enable trigger command
if (me.earthme.luminol.config.modules.experiment.CommandConfig.waypointsAndWaypointCommand) WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later // Luminol - Restore waypoints
WeatherCommand.register(this.dispatcher);
WorldBorderCommand.register(this.dispatcher);
@@ -18,7 +18,7 @@ index 0c0775bbb0c0ba0c37d1b884bb106b5250e94750..0dfb25ad032429a2aea7aa441dd5fd18
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 0e543348e48fdf2131dfa1460e37db238d02988c..b69698f47ccb0f1ac3eeea05a02ab9d798319b44 100644
index 552fd994ee30deb6e9f4228b17a2883cf26b164c..6f7e5d62901733df08c6beafbda2e54bc1c5f917 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -167,7 +167,7 @@ public abstract class Entity
@@ -30,7 +30,7 @@ index 0e543348e48fdf2131dfa1460e37db238d02988c..b69698f47ccb0f1ac3eeea05a02ab9d7
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
static boolean isLevelAtLeast(ValueInput input, int level) {
@@ -6412,4 +6412,46 @@ public abstract class Entity
@@ -6432,4 +6432,46 @@ public abstract class Entity
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -0,0 +1,123 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add tick rate support
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 981f63b75584dbcb4bb0d5672e8c8bb140c52f9d..6e8ee04967afa410ce9dccff34bf9a43201694fd 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -371,6 +371,14 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Lophine start - Add a config to enable tick command
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ rateManager.reduceSprintTicks();
+ rateManager.endTickWork();
+ }
+ // Lophine end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index f60b3b40c7dc5820abc726abc8d094ed873edf6c..917d6965e91527fc79d545c041765f78a357eac2 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Lophine - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Lophine - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -528,8 +528,24 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Lophine start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ if (rateManager.isSprinting() && rateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = rateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Lophine end - Add tick command support
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index 8d0f810100a4eac65831913feeb9a9eeb0e6006a..ca35415e152dc63cb9f4ae8da8b06766600922fd 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Lophine start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Lophine end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index cae943bae4701f74b46a49d68da83ae797841590..d8f5f1b2f75a4e23556fb016ad47f2cefe1309ce 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Lophine - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -22,14 +22,14 @@ public class TickCommand {
Commands.literal("tick")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
-/* .then(
+ .then(
Commands.literal("rate")
.then(
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
)
- )*/
+ )
.then(
Commands.literal("step")
.executes(c -> step(c.getSource(), 1))
@@ -1,186 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add config to enable tick command
Because of some bug, we disabled sprint command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index fc6402dd0a47f5b2792aa8a21703bfee18dd2388..96423a1a429f4fb1c975ad10726fe0e1ff70a6ad 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -338,6 +338,11 @@ public final class RegionizedServer {
this.randomWalk();
*/
++this.tickCount;
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.tick();
+ }
+ // Luminol end - Add a config to enable tick command
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -366,6 +371,13 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.reduceSprintTicks();
+ MinecraftServer.tickRateManager.endTickWork();
+ }
+ // Luminol end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
@@ -513,7 +525,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final long tickCount) {
- if (world.tickTime) {
+ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + tickCount);
}
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 8b09834ec36f62a73e388124129afbdfa47e6c25..ce0ace6a0c6b11f124b601d97491fee102b36554 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Luminol - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Luminol - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -525,8 +525,23 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Luminol start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = MinecraftServer.tickRateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Luminol end - Add tick command support
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
@@ -575,6 +590,11 @@ public final class TickRegionScheduler {
try {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.endTickWork();
+ }
+ // Luminol end - Add a config to enable tick command
} catch (final Throwable thr) {
this.scheduler.regionFailed(this, false, thr);
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index f54f6047f326189329e11338b17105f5555dde12..6f3143deb9e5ff17fae5920b0a4ba34e3d9545c4 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -265,7 +265,11 @@ public class Commands {
TeleportCommand.register(this.dispatcher);
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
- //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Luminol end - Add a config to enable tick command
TimeCommand.register(this.dispatcher, context);
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 82315368d5580563fc77548f22a65d04ec73b622..8dcd684189d953aabddc4f62a3ecc5807c949ce6 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -283,7 +283,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private @Nullable String serverId;
public MinecraftServer.ReloadableResources resources;
private final StructureTemplateManager structureTemplateManager;
- private final ServerTickRateManager tickRateManager;
+ public static ServerTickRateManager tickRateManager; // Luminol - Add tick command support
private final ServerDebugSubscribers debugSubscribers = new ServerDebugSubscribers(this);
protected WorldData worldData;
private LevelData.RespawnData effectiveRespawnData = LevelData.RespawnData.DEFAULT;
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index 8d0f810100a4eac65831913feeb9a9eeb0e6006a..afcab27006558f5d379df723968a612c1cadba60 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Luminol start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Luminol end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index 2dd0a8f2399a83b90356fcf0777bd1aec8eef5a9..c3dcfb633877ef230ab48a455ad4f5a1d601ba48 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Luminol - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -40,7 +40,7 @@ public class TickCommand {
.executes(c -> step(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
)
)
- .then(
+/* .then(
Commands.literal("sprint")
.then(Commands.literal("stop").executes(c -> stopSprinting(c.getSource())))
.then(
@@ -48,7 +48,7 @@ public class TickCommand {
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{"60s", "1d", "3d"}, b))
.executes(c -> sprint(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
)
- )
+ )*/
.then(Commands.literal("unfreeze").executes(c -> setFreeze(c.getSource(), false)))
.then(Commands.literal("freeze").executes(c -> setFreeze(c.getSource(), true)))
);
@@ -38,7 +38,7 @@ index c147a1acd4fd9f94c73bee69febf651ca00c28ce..f8004bf74edeabce871515fb73fa00f3
if (count > maxAllowedCount) {
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", maxAllowedCount, prototypeItemStack.getDisplayName()));
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 47beff71ed33e7fbd6fe6cd47aa955233af41f04..8e5b79db12882432de575f2a76aa36eac6fc8f51 100644
index 15470867ed0f668fd3ba9c1fa24f84b3de8cb756..4f243a4d3143bae799619e2ec76366c961c62da6 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3229,7 +3229,7 @@ public class ServerGamePacketListenerImpl
@@ -353,7 +353,7 @@ index ee86a63c8d0d4c798ad09da87598d22c0e516840..57061d97bd368bfe934157293471fd54
public @Nullable Identifier getNoItemIcon() {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index fa588ab87f978b8aeaef0f1849aa532e5a4ad940..dd4a92a0ea94d16669535bde9b6728515dafe7f4 100644
index 718a7786d73852368b6e911716fb494cc4770ef1..61466aa6d11af2858fa2898ef5b4b7515f4365df 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -160,7 +160,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
@@ -36,7 +36,7 @@ index e9f86409bf9351e85ed31e747d9350dbf0cc441f..1f8f4d979d8766d6ba385f74cf8fcf8e
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 8dcd684189d953aabddc4f62a3ecc5807c949ce6..0bedaa20bc2cae75a48357e69740ada2380a03dd 100644
index 4991b8a925d9431d80f42a4480d76d6602a85347..9e290fa626caffac148920c54479a75ad0919e70 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2037,6 +2037,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/9d2bd3f7b0a48f00d
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index c380ab9f059da6219691e8bccd4f82b9ec5483b3..b2ea90b0ab461d202d492411471d2412a9c5d303 100644
index 047c605eb087667e10da557864ad931dadebd274..e9547fb9be40c3e999a9172acb48037595439396 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -3158,7 +3158,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index afcab27006558f5d379df723968a612c1cadba60..ddab99a4cc70a1aa365208cb52d8d9b880cdeff6 100644
index ca35415e152dc63cb9f4ae8da8b06766600922fd..033715812acb8f98a7c7d895d115043e232d5161 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -139,4 +139,10 @@ public class ServerTickRateManager extends TickRateManager {
@@ -23,7 +23,7 @@ index afcab27006558f5d379df723968a612c1cadba60..ddab99a4cc70a1aa365208cb52d8d9b8
+ // Leaves end - servux
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index b2ea90b0ab461d202d492411471d2412a9c5d303..049339ae33569d627d2a00ef6cab9cad02c4c014 100644
index e9547fb9be40c3e999a9172acb48037595439396..0ff635e6956a9935ad6d11e5c7bac189c51244b6 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2584,6 +2584,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -9,7 +9,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 8e5b79db12882432de575f2a76aa36eac6fc8f51..977a4ac391b8cf8b59c5c77becf9a5951d513526 100644
index 4f243a4d3143bae799619e2ec76366c961c62da6..e6c09a4b780dafbf55793fabf864f66aa6e5604d 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -346,9 +346,12 @@ public class ServerGamePacketListenerImpl
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 4882df428369e87bcf23b532dd970b13b3adfb88..e51f99de547f09f98b9e351bf84d8411994b62bc 100644
index da9706f866aabee6939cacbfbcc9def01fde0326..3708f9ffc46a5b1c038c0e7b2ce84802e2b22397 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -757,6 +757,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -772,6 +772,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
public void setLoaded(final boolean loaded) {
this.loaded = loaded;
@@ -9,7 +9,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 977a4ac391b8cf8b59c5c77becf9a5951d513526..bc38b16dd296cca9bc5556b95117794e633a9c27 100644
index e6c09a4b780dafbf55793fabf864f66aa6e5604d..57e3180dc4568f58d5b69d2b9656d7cf9bbae81f 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3902,7 +3902,7 @@ public class ServerGamePacketListenerImpl
@@ -13,7 +13,7 @@ MasaGadget(https://github.com/plusls/MasaGadget)
litematica(https://github.com/maruohon/litematica)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index bc38b16dd296cca9bc5556b95117794e633a9c27..57aff87cc7be0cb7136689412490cd399eff15eb 100644
index 57e3180dc4568f58d5b69d2b9656d7cf9bbae81f..96088ba53f043c8bc6971bc62e5dcccd98523698 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2183,7 +2183,7 @@ public class ServerGamePacketListenerImpl
@@ -60,7 +60,7 @@ index d5d499226d0b2c2adfae7bbb4c28c96c80411c44..cb0a4a9865df69e5504a86de6c144bc4
stateForPlacement = possibleState;
break;
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
index 0cdd88e530c660b65f3eb331b37cbd2c69fc2ff5..62dec122c5e23150dc107d3fab5a552f86d34565 100644
index c5f4e0570a82dfcc2ba88023f3301f69afa41cc5..30f7e8f5e3e9440713e36ee25c90150b6b93c6ff 100644
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -516,6 +516,32 @@ public class Block extends BlockBehaviour implements ItemLike {
@@ -33,7 +33,7 @@ index efbbc1a40d203a2818eeda2a4e938b9a6117f1c3..6b85a5ad9af0c57a0d4d5b55f62b82c5
private boolean encrypted;
private final java.util.concurrent.atomic.AtomicBoolean disconnectionHandled = new java.util.concurrent.atomic.AtomicBoolean(false); // Folia - region threading - may be called concurrently during configuration stage
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a7546eb15 100644
index 9e290fa626caffac148920c54479a75ad0919e70..75d93d7d8bc6077dd80e499cd43327a4afe58f51 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -297,6 +297,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -45,15 +45,24 @@ index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a
public static <S extends MinecraftServer> S spin(final Function<Thread, S> factory) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
AtomicReference<S> serverReference = new AtomicReference<>();
@@ -1120,6 +1122,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
+ this.getBotList().removeAll(); // Leaves - save or remove bot
// CraftBukkit start
if (this.server != null) {
if (false) this.server.spark.disable(); // Paper - spark // Luminol - Force disable builtin spark
@@ -1695,7 +1698,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1226,6 +1228,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.safeShutdown(wait, false);
}
public void safeShutdown(final boolean wait, final boolean isRestarting) {
+ // Lophine start - Folia changes
+ safeShutdown(wait, isRestarting, false);
+ }
+
+ public void safeShutdown(final boolean wait, final boolean isRestarting, boolean force) {
+ if (!force && !this.getBotList().forceShutdown && !this.getBotList().removeAll()) { // Leaves - save or remove bot
+ this.getPlayerList().broadcastSystemMessage(Component.literal("Bot Still need to save, please wait! If you want to shuntdown without bot data saving, please use /stop force"), false);
+ return;
+ }
+ // Lophine end - Folia changes
this.isRestarting = isRestarting;
this.hasLoggedStop = true; // Paper - Debugging
if (this.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
@@ -1695,7 +1707,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int emptyTickThreshold = this.pauseWhenEmptySeconds() * 20;
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
if (false && emptyTickThreshold > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
@@ -62,7 +71,7 @@ index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1827,6 +1830,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1827,6 +1839,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isSaving = true;
if (playerSaveInterval > 0) {
this.playerList.saveAll(playerSaveInterval);
@@ -70,7 +79,7 @@ index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a
}
if (region == null && fullSave) { // Folia - region threading - don't auto save level data
this.saveGlobalData(false);
@@ -2065,6 +2069,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2065,6 +2078,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
protected void tickConnection() {
this.getConnection().tick();
@@ -78,7 +87,7 @@ index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a
}
public void forceGameTimeSynchronization() {
@@ -3270,6 +3275,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -3270,6 +3284,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.debugSubscribers;
}
@@ -213,6 +222,22 @@ index 636f56bfc0e9075b257e2eb14e858975bdedd801..20cbc0e65fea3fc2d0033259c2f35e15
if (!list.isOp(player)) {
list.op(player);
count++;
diff --git a/net/minecraft/server/commands/StopCommand.java b/net/minecraft/server/commands/StopCommand.java
index e9c9a468f046832e8eaa999bb57da261b4633604..2efe24c0378a80dd2750b10a54c1887816236c1a 100644
--- a/net/minecraft/server/commands/StopCommand.java
+++ b/net/minecraft/server/commands/StopCommand.java
@@ -11,6 +11,10 @@ public class StopCommand {
c.getSource().sendSuccess(() -> Component.translatable("commands.stop.stopping"), true);
c.getSource().getServer().halt(false);
return 1;
- }));
+ }).then(Commands.literal("force").requires(Commands.hasPermission(Commands.LEVEL_OWNERS)).executes(c -> {
+ c.getSource().sendSuccess(() -> Component.translatable("commands.stop.stopping"), true);
+ c.getSource().getServer().safeShutdown(false, false, true);
+ return 1;
+ })));
}
}
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 1bc1e9a77dca7acfe5f989f6439f185d0d2e20a6..1790e8c141a8d3f7ccf4b11f9a28b3582325e317 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
@@ -252,7 +277,7 @@ index 0dfb25ad032429a2aea7aa441dd5fd1848a6c617..215f2a40921cc8e6b181c0a34aa1bbaf
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 049339ae33569d627d2a00ef6cab9cad02c4c014..e05705884a285143b8a3ebad00cb489efe47d532 100644
index 0ff635e6956a9935ad6d11e5c7bac189c51244b6..8bfb2afd7199b2739ccfbab4ad68e030e722db7e 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -240,6 +240,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -309,19 +334,10 @@ index 049339ae33569d627d2a00ef6cab9cad02c4c014..e05705884a285143b8a3ebad00cb489e
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00ce41c64bb 100644
index f3afab1100a35cc9ab091944de93d1f30ef040a7..423652d0ccef5c6a3b93480401c3d0f672bbf8a5 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -23,6 +23,8 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
+
+import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import net.minecraft.ChatFormatting;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
@@ -229,7 +231,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -229,7 +229,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
public ServerGamePacketListenerImpl connection;
private final MinecraftServer server;
@@ -330,7 +346,7 @@ index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00c
private final PlayerAdvancements advancements;
private final ServerStatsCounter stats;
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
@@ -250,7 +252,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -250,7 +250,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private @Nullable Entity camera;
public boolean isChangingDimension;
public boolean seenCredits = false;
@@ -339,7 +355,7 @@ index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00c
private @Nullable Vec3 levitationStartPos;
private int levitationStartTime;
private boolean disconnected;
@@ -1514,7 +1516,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1514,7 +1514,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Luminol End - Cross Region Damage trace
@@ -348,12 +364,12 @@ index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00c
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
.getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS)
@@ -2180,6 +2182,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -2180,6 +2180,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
this.teleportSpectators(transition, oldLevel);
+ // Leaves start - bot support
+ if (FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
+ }
+ // Leaves end - bot support
@@ -426,24 +442,15 @@ index 484714beb5f7cdf8178834c5edd4f847fb06ebb8..ba7a280aad07f36366c15cd158b36ca9
// Paper start - utility method for common conversion back to the game profile
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bbf6495770 100644
index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f0da2047c 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -22,6 +22,8 @@ import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Predicate;
+
+import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.BlockPos;
@@ -319,6 +321,19 @@ public abstract class PlayerList {
@@ -319,6 +319,19 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+ // Leaves start - bot support
+ if (FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -458,19 +465,19 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bb
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -791,6 +806,11 @@ public abstract class PlayerList {
@@ -791,6 +804,11 @@ public abstract class PlayerList {
respawnReason
).callEvent();
// Paper end
+ // Leaves start - bot support
+ if (FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
+ }
+ // Leaves end - bot support
return player;
}
@@ -893,11 +913,16 @@ public abstract class PlayerList {
@@ -893,11 +911,16 @@ public abstract class PlayerList {
public String[] getPlayerNamesArray() {
List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
@@ -488,7 +495,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bb
return names;
}
@@ -1016,8 +1041,15 @@ public abstract class PlayerList {
@@ -1016,8 +1039,15 @@ public abstract class PlayerList {
|| this.allowCommandsForAllPlayers;
}
@@ -506,7 +513,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bb
}
public void broadcast(
@@ -1360,7 +1392,13 @@ public abstract class PlayerList {
@@ -1360,7 +1390,13 @@ public abstract class PlayerList {
}
public @Nullable ServerPlayer getPlayer(final UUID uuid) {
@@ -522,7 +529,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bb
public @Nullable ServerPlayer getPlayer(final String playerName) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index b69698f47ccb0f1ac3eeea05a02ab9d798319b44..b073a91fd67d092713c53db6f3df75c655dc8fcd 100644
index 6f7e5d62901733df08c6beafbda2e54bc1c5f917..07c5fed7b0bf3ecefb54ccb0bfb922c2f11f7939 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1257,7 +1257,7 @@ public abstract class Entity
@@ -534,7 +541,7 @@ index b69698f47ccb0f1ac3eeea05a02ab9d798319b44..b073a91fd67d092713c53db6f3df75c6
this.checkFallDamage(movement.y, this.onGround(), effectState, effectPos);
}
@@ -1593,7 +1593,7 @@ public abstract class Entity
@@ -1602,7 +1602,7 @@ public abstract class Entity
return colliders.isEmpty() ? maxDistance : -Shapes.collide(Direction.Axis.Y, aabb, colliders, -maxDistance);
}
@@ -712,7 +719,7 @@ index fa1f7dd22959632aaa54e72c8caf13ea072e7ca7..ae6056c3b6ae3eebdfb59cf54d7333df
final Player player, final ClickAction clickAction, final Slot slot, final ItemStack clicked, final ItemStack carried
) {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index dd4a92a0ea94d16669535bde9b6728515dafe7f4..77f3bf9d9c0bb08a151adf1abd22e22d0fc83bf3 100644
index 61466aa6d11af2858fa2898ef5b4b7515f4365df..78dd1f8fbbb1e7633142f7038de29124312878dd 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -453,7 +453,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
@@ -84,10 +84,10 @@ index 7e3912b8b29e40eb3347f1451b0fd3ebee2af4f1..0834e402e6af7028e08851378e15390e
result.add(player);
if (result.size() >= limit) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3 100644
index 75d93d7d8bc6077dd80e499cd43327a4afe58f51..3b9a4f4b5794faa4955018858c94fd5c2d6ada3d 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1921,7 +1921,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1930,7 +1930,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
private ServerStatus.Players buildPlayerStatus() {
@@ -96,7 +96,7 @@ index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d
int maxPlayers = this.getMaxPlayers();
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
@@ -2142,7 +2142,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2151,7 +2151,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public int getPlayerCount() {
@@ -105,7 +105,7 @@ index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d
}
public String[] getPlayerNames() {
@@ -2354,7 +2354,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2363,7 +2363,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} else {
int count = 0;
@@ -114,7 +114,7 @@ index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d
player.getBukkitEntity().taskScheduler.schedule((ServerPlayer updatedPlayer) -> { // Folia - region threading
// Paper start - Expand PlayerGameModeChangeEvent
org.bukkit.event.player.PlayerGameModeChangeEvent event = updatedPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null); // Folia - region threading
@@ -2541,7 +2541,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2550,7 +2550,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (Thread.currentThread() != this.serverThread) return; // Paper
// Paper start - we don't need to save everything, just advancements
// this.getPlayerList().saveAll();
@@ -123,7 +123,7 @@ index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d
player.getAdvancements().save();
}
// Paper end - we don't need to save everything, just advancements
@@ -2677,7 +2677,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2686,7 +2686,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
PlayerList playerList = this.getPlayerList();
UserWhiteList whiteList = playerList.getWhiteList();
@@ -285,7 +285,7 @@ index 37c9f983ae89c497f44a1b7967d741abf909e0a0..d7fb2505f2a86ca0d81f144624ef2e1a
this.setListData(players);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index e05705884a285143b8a3ebad00cb489efe47d532..c51b0075cd650085cd991bc89396f605cb520442 100644
index 8bfb2afd7199b2739ccfbab4ad68e030e722db7e..8d6a5d2ab4589f81abdd4ae939f197051e9523fc 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -3100,7 +3100,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -307,10 +307,10 @@ index e05705884a285143b8a3ebad00cb489efe47d532..c51b0075cd650085cd991bc89396f605
}
// Leaves end - skip
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41e33e775c 100644
index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1f82c9279 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -132,6 +132,7 @@ public abstract class PlayerList {
@@ -130,6 +130,7 @@ public abstract class PlayerList {
private int simulationDistance;
private boolean allowCommandsForAllPlayers;
private int sendAllPlayerInfoIn;
@@ -318,7 +318,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -193,6 +194,7 @@ public abstract class PlayerList {
@@ -191,6 +192,7 @@ public abstract class PlayerList {
private boolean countConnection(Connection conn, int limit) {
synchronized (this.connectionsStateLock) {
@@ -326,7 +326,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
int count = this.usersCountedAgainstLimit.size();
if (count >= limit) {
return false;
@@ -223,6 +225,124 @@ public abstract class PlayerList {
@@ -221,6 +223,124 @@ public abstract class PlayerList {
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
@@ -387,7 +387,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+
+ // Leaves start - bot support
+ if (FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -451,7 +451,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
public void placeNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -296,6 +416,7 @@ public abstract class PlayerList {
@@ -294,6 +414,7 @@ public abstract class PlayerList {
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
@@ -459,7 +459,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
@@ -515,6 +636,7 @@ public abstract class PlayerList {
@@ -513,6 +634,7 @@ public abstract class PlayerList {
}
protected void save(final ServerPlayer player) {
@@ -467,7 +467,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
player.lastSave = System.nanoTime(); // Folia - region threading - changed to nanoTime tracking
this.playerIo.save(player);
@@ -529,6 +651,47 @@ public abstract class PlayerList {
@@ -527,6 +649,47 @@ public abstract class PlayerList {
}
}
@@ -515,7 +515,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
public net.kyori.adventure.text.@Nullable Component remove(final ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
// Paper start - Fix kick event leave message not being sent
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
@@ -602,6 +765,7 @@ public abstract class PlayerList {
@@ -600,6 +763,7 @@ public abstract class PlayerList {
player.getBukkitEntity().packetProcessor.close(); // Folia - region threading
player.getAdvancements().stopListening();
this.players.remove(player);
@@ -523,7 +523,7 @@ index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
this.server.getCustomBossEvents().onPlayerDisconnect(player);
UUID uuid = player.getUUID();
@@ -912,15 +1076,15 @@ public abstract class PlayerList {
@@ -910,15 +1074,15 @@ public abstract class PlayerList {
}
public String[] getPlayerNamesArray() {
@@ -21,7 +21,7 @@ index e302c6198d71782b524391329aa5c89d2b3e0ccf..2312803297321f66c9057bc54ce56dd1
} else {
this.followingPlayer = null;
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 38689fa466a20c64f9916ee32a57a9fdb58d9403..7d514537ee38f9b9366692bc969ff503d883aa16 100644
index 38689fa466a20c64f9916ee32a57a9fdb58d9403..ea5de9aca4908ed972c4f44bff635f2cc423a04f 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -279,8 +279,8 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -59,7 +59,7 @@ index 38689fa466a20c64f9916ee32a57a9fdb58d9403..7d514537ee38f9b9366692bc969ff503
+ // Leaves start - creative no clip
+ public boolean isCreativeFlyOrSpectator() {
+ return isSpectator() || (fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && isCreative() && getAbilities().flying);
+ return isSpectator() || (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && isCreative() && getAbilities().flying);
+ }
+
+ public boolean canSpectatingPlace(final net.minecraft.world.level.LevelReader world, final BlockState state, final BlockPos pos, final net.minecraft.world.phys.shapes.CollisionContext context) {
@@ -81,7 +81,7 @@ index 38689fa466a20c64f9916ee32a57a9fdb58d9403..7d514537ee38f9b9366692bc969ff503
public boolean isPickable() {
return !this.isSpectator() && super.isPickable();
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f..06160c24f1ffbe1445284bc81598cabb3ad20477 100644
index 2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f..07b84bd0144e133d13e8e033a8998f3cf674f746 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -158,8 +158,9 @@ public class BlockItem extends Item {
@@ -91,12 +91,12 @@ index 2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f..06160c24f1ffbe1445284bc81598cabb
+ CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.placementContext(player); // Leaves - creative no clip
boolean canBuild = (!this.mustSurvive() || stateForPlacement.canSurvive(world, context.getClickedPos()))
- && world.checkEntityCollision(stateForPlacement, player, CollisionContext.placementContext(player), context.getClickedPos(), true); // Paper - Cancel hit for vanished players
+ && ((fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, stateForPlacement, context.getClickedPos(), collisionContext) : world.checkEntityCollision(stateForPlacement, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip
+ && ((fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, stateForPlacement, context.getClickedPos(), collisionContext) : world.checkEntityCollision(stateForPlacement, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip
org.bukkit.entity.Player bukkitPlayer = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
index cb0a4a9865df69e5504a86de6c144bc4450bd19a..a40a98bb48bb14c49670ba55d2a2e8d7e9d0d178 100644
index cb0a4a9865df69e5504a86de6c144bc4450bd19a..596fb91fccb4c8d6854fa859f9ee357c6d22a81e 100644
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
@@ -44,7 +44,7 @@ public class StandingAndWallBlockItem extends BlockItem {
@@ -104,7 +104,7 @@ index cb0a4a9865df69e5504a86de6c144bc4450bd19a..a40a98bb48bb14c49670ba55d2a2e8d7
// CraftBukkit start
if (stateForPlacement != null) {
- boolean defaultReturn = level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty());
+ boolean defaultReturn = (fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(level, stateForPlacement, pos, CollisionContext.empty()) : level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); // Leaves - creative no clip
+ boolean defaultReturn = (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(level, stateForPlacement, pos, CollisionContext.empty()) : level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); // Leaves - creative no clip
org.bukkit.entity.Player player = (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer serverPlayer) ? serverPlayer.getBukkitEntity() : null;
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), pos), player, stateForPlacement.asBlockData(), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
@@ -98,7 +98,7 @@ index 27389ff98942e27c2a877ea5b671caa31353d18c..e9e5f929d638d3ddf279423d3e23b3f8
NaturalSpawner.spawnForChunk(this.level, chunk, spawnCookie, spawningCategories);
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index c51b0075cd650085cd991bc89396f605cb520442..fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54 100644
index 8d6a5d2ab4589f81abdd4ae939f197051e9523fc..54011666a2f358fe38ca03bc39d68d122011c796 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -808,6 +808,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -32,10 +32,10 @@ index 24f5b890b0126fc817863f99b676da1a548f7608..78bea975c15130c91c90f48c868ac32e
throw PacketUtils.makeReportedException(var3, this.packet, this.listener);
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3..06482d945e4f7b1adc56168ad43bea34484a6fa9 100644
index 3b9a4f4b5794faa4955018858c94fd5c2d6ada3d..19bef18e606d873308d08987d90e298703efb574 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2010,11 +2010,26 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2019,11 +2019,26 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler
level.tick(haveTime, region); // Folia - region threading
@@ -66,7 +66,7 @@ index 48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3..06482d945e4f7b1adc56168ad43bea34
profiler.pop();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54..f44f772628f5705c5dee9cb92295362ba09c20ce 100644
index 54011666a2f358fe38ca03bc39d68d122011c796..3496696c6b023e7df95027917b3391557dddd8d0 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -967,7 +967,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -74,7 +74,7 @@ index fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54..f44f772628f5705c5dee9cb92295362b
profiler.push("tick");
- this.guardEntityTick(this::tickNonPassenger, entity);
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ try {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
@@ -88,10 +88,10 @@ index fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54..f44f772628f5705c5dee9cb92295362b
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 7f6d4118ede7e02fdea8961fd736d00ce41c64bb..91ec7f6b751159f2935165268166f44d27579426 100644
index 423652d0ccef5c6a3b93480401c3d0f672bbf8a5..65965089d184695588c74294afb2f5c0b28bbf17 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1132,6 +1132,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1130,6 +1130,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
// Folia - region threading - move to main tick loop where we can detect duplicates
// CraftBukkit end
@@ -103,10 +103,10 @@ index 7f6d4118ede7e02fdea8961fd736d00ce41c64bb..91ec7f6b751159f2935165268166f44d
CrashReport report = CrashReport.forThrowable(var4, "Ticking player");
CrashReportCategory category = report.addCategory("Player being ticked");
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index b073a91fd67d092713c53db6f3df75c655dc8fcd..ba3eabe8208c45f8adbe431965a2d936fea93fdf 100644
index 07c5fed7b0bf3ecefb54ccb0bfb922c2f11f7939..8a92d1748464ef8d1d33e51163a3e0d74120e5a7 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1450,7 +1450,15 @@ public abstract class Entity
@@ -1459,7 +1459,15 @@ public abstract class Entity
}
if (shouldVibrate) {
@@ -124,7 +124,7 @@ index b073a91fd67d092713c53db6f3df75c655dc8fcd..ba3eabe8208c45f8adbe431965a2d936
return true;
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..80d10b42106749254eb5f757986838acc1c064d2 100644
index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..c0b086fd5084fc0e39b91d3f6bd6904ef19f4157 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -181,7 +181,14 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -135,7 +135,7 @@ index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..80d10b42106749254eb5f757986838ac
+ try {
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ } catch (ClassCastException ex) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
+ }
+ throw ex;
@@ -144,7 +144,7 @@ index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..80d10b42106749254eb5f757986838ac
public @Nullable DyeColor getColor() {
diff --git a/net/minecraft/world/level/block/state/StateHolder.java b/net/minecraft/world/level/block/state/StateHolder.java
index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..a359d9ce555b9c8ec01ed71b305ab8efa80c3892 100644
index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..6d3af2481e81795771ac8f82d984681ec8c9e0b9 100644
--- a/net/minecraft/world/level/block/state/StateHolder.java
+++ b/net/minecraft/world/level/block/state/StateHolder.java
@@ -118,7 +118,14 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
@@ -153,7 +153,7 @@ index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..a359d9ce555b9c8ec01ed71b305ab8ef
}
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ org.leavesmc.leaves.util.UpdateSuppressionException exception = new org.leavesmc.leaves.util.UpdateSuppressionException(null, null, null, null, iae);
+ if (exception.getStackTrace()[1].getClassName().startsWith("net.minecraft")) {
+ throw exception;
@@ -164,10 +164,10 @@ index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..a359d9ce555b9c8ec01ed71b305ab8ef
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index e51f99de547f09f98b9e351bf84d8411994b62bc..7e7292dd8fcb27fdb8e69e42e5383b6c22154747 100644
index 3708f9ffc46a5b1c038c0e7b2ce84802e2b22397..7760a711f4c49fc3499bf71fabb59ee8b4c85083 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -385,6 +385,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -400,6 +400,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
return null;
} else {
Block newBlock = state.getBlock();
@@ -175,7 +175,7 @@ index e51f99de547f09f98b9e351bf84d8411994b62bc..7e7292dd8fcb27fdb8e69e42e5383b6c
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(localX, y, localZ, state);
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(localX, y, localZ, state);
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(localX, y, localZ, state);
@@ -453,6 +454,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -468,6 +469,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
this.markUnsaved();
return oldState;
}
@@ -187,20 +187,20 @@ index e51f99de547f09f98b9e351bf84d8411994b62bc..7e7292dd8fcb27fdb8e69e42e5383b6c
}
}
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..44731e230869f0df058f6a426277befbb0d559e4 100644
index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..6d25139a94df7c0442cc9fea96d5839ce8a23d54 100644
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
@@ -87,9 +87,20 @@ public interface NeighborUpdater {
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Spigot start
} catch (StackOverflowError ex) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, changedBlock, null, ex);
+ }
level.lastPhysicsProblem = pos.immutable();
// Spigot end
} catch (Throwable var9) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(level, pos, changedBlock);
+ throw exception;
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 80d10b42106749254eb5f757986838acc1c064d2..ffa76dc1338c6c892a42b2148f9f01c933660b98 100644
index c0b086fd5084fc0e39b91d3f6bd6904ef19f4157..8259f530ec50554906c254b60f1e964b52c02852 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -182,7 +182,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -16,9 +16,9 @@ index 80d10b42106749254eb5f757986838acc1c064d2..ffa76dc1338c6c892a42b2148f9f01c9
protected int getAnalogOutputSignal(final BlockState state, final Level level, final BlockPos pos, final Direction direction) {
try {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.shulkerBoxCCEReintroduced
+ ? AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container)level.getBlockEntity(pos))
+ : AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
} catch (ClassCastException ex) {
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
@@ -3,26 +3,28 @@ From: Bacteriawa <A3167717663@hotmail.com>
Date: Wed, 14 Jun 2023 12:07:07 +0800
Subject: [PATCH] Leaves: Redstone ignore upwards update
(Carpet: dustTrapdoorReintroduced)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
index 45e11737bc2558a4ebfffe133d43111f45dd7d16..b6005e5e60ac571396d584c7f4dec3975a6f9923 100644
index 45e11737bc2558a4ebfffe133d43111f45dd7d16..d3bcef3fa3228c3869041754b2c18dfc987aac35 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -59,6 +59,9 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && directionToNeighbour == Direction.DOWN) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
return directionToNeighbour == Direction.DOWN && !this.canSurviveOn(level, neighbourPos, neighbourState)
? Blocks.AIR.defaultBlockState()
: super.updateShape(state, level, ticks, pos, directionToNeighbour, neighbourPos, neighbourState, random);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 759eb347299813c20226cc2fc5dc7718d12b7f56..66a05f099a263b0c9220f1416f3cf1221422cc20 100644
index 759eb347299813c20226cc2fc5dc7718d12b7f56..619f5e37919693fc5976aedefed3bb5428395439 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -179,7 +179,9 @@ public class RedStoneWireBlock extends Block {
@@ -30,7 +32,7 @@ index 759eb347299813c20226cc2fc5dc7718d12b7f56..66a05f099a263b0c9220f1416f3cf122
) {
if (directionToNeighbour == Direction.DOWN) {
- return !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced
+ ? state
+ : !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
} else if (directionToNeighbour == Direction.UP) {
@@ -41,20 +43,20 @@ index 759eb347299813c20226cc2fc5dc7718d12b7f56..66a05f099a263b0c9220f1416f3cf122
BlockState relativeState = level.getBlockState(relativePos);
if (canConnectUp) {
- boolean isPlaceableAbove = relativeState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, relativePos, relativeState);
+ boolean isPlaceableAbove = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && relativeState.getBlock() instanceof TrapDoorBlock)
+ boolean isPlaceableAbove = (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && relativeState.getBlock() instanceof TrapDoorBlock)
+ || this.canSurviveOn(level, relativePos, relativeState);
if (isPlaceableAbove && shouldConnectTo(level.getBlockState(relativePos.above()))) {
if (relativeState.isFaceSturdy(level, relativePos, direction.getOpposite())) {
return RedstoneSide.UP;
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
index d301ca4c91e75d715998aa7ed155fd44ccd64785..13928e667cfa36e2ebf45b30caf4c5be28f2f725 100644
index d301ca4c91e75d715998aa7ed155fd44ccd64785..cc2694d0fc3c9bbe5e91771b3aef8ffb749515b4 100644
--- a/net/minecraft/world/level/block/RepeaterBlock.java
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
@@ -70,6 +70,9 @@ public class RepeaterBlock extends DiodeBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && directionToNeighbour == Direction.DOWN) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
if (directionToNeighbour == Direction.DOWN && !this.canSurviveOn(level, neighbourPos, neighbourState)) {
@@ -5,39 +5,30 @@ Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..dad62b80578f27cc39985ee6ded705bf3cc5d117 100644
index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..1a426e1aa456a8ea432f62483c3be5c328b97953 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -44,6 +44,8 @@ import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.pathfinder.PathTypeCache;
import net.minecraft.world.level.redstone.CollectingNeighborUpdater;
+import net.minecraft.world.level.redstone.InstantNeighborUpdater;
+import net.minecraft.world.level.redstone.NeighborUpdater;
import net.minecraft.world.level.saveddata.WanderingTraderData;
import net.minecraft.world.ticks.LevelTicks;
import org.bukkit.craftbukkit.block.CraftBlockState;
@@ -506,7 +508,7 @@ public final class RegionizedWorldData {
@@ -506,7 +506,7 @@ public final class RegionizedWorldData {
public long lastMidTickExecuteFailure;
// From Level
public boolean populating;
- public final CollectingNeighborUpdater neighborUpdater;
+ public final NeighborUpdater neighborUpdater;
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater;
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public final Map<BlockPos, CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
@@ -567,7 +569,9 @@ public final class RegionizedWorldData {
@@ -567,7 +567,9 @@ public final class RegionizedWorldData {
this.world = world;
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
- this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater
+ ? new InstantNeighborUpdater(world)
+ this.neighborUpdater = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.instantBlockUpdaterReintroduced
+ ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world)
+ : new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
this.nearbyPlayers = new NearbyPlayers(world);
this.wireHandler = new alternate.current.wire.WireHandler(world);
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
@@ -896,4 +900,4 @@ public final class RegionizedWorldData {
@@ -896,4 +898,4 @@ public final class RegionizedWorldData {
public int getChunkCount() {
return this.chunks.size();
}
@@ -45,7 +36,7 @@ index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..dad62b80578f27cc39985ee6ded705bf
\ No newline at end of file
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index f44f772628f5705c5dee9cb92295362ba09c20ce..ee10aceeddb59241e4b1d0bea021001787ea2f88 100644
index 3496696c6b023e7df95027917b3391557dddd8d0..d8718805a965db11dfce8ed7f5ea65a638cc4510 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -999,11 +999,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -9,7 +9,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 06160c24f1ffbe1445284bc81598cabb3ad20477..ca3f31a72060f797115787302d32a019fa8243e0 100644
index 07b84bd0144e133d13e8e033a8998f3cf674f746..9c016e7d93e4c44ddf2df520e5c57d92a0e085b3 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -69,20 +69,8 @@ public class BlockItem extends Item {
@@ -34,10 +34,10 @@ index 06160c24f1ffbe1445284bc81598cabb3ad20477..ca3f31a72060f797115787302d32a019
// CraftBukkit start - special case for handling block placement with water lilies, frog spawn and snow buckets
if (player != null && (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem)) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 7e7292dd8fcb27fdb8e69e42e5383b6c22154747..b7ba4d8ed2cc65ba0e85a3cdf8b6568a7c9c02f1 100644
index 7760a711f4c49fc3499bf71fabb59ee8b4c85083..ef3508dc4c8b3a9c8a6c7ff520cf51a68d6a13d9 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1000,12 +1000,6 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -1015,12 +1015,6 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
profiler.pop();
} catch (Throwable var5) {
@@ -8,14 +8,15 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java
index 1311d4936f84652c5ffc51544f99cb98fc293906..b4cbe16c9660f3e88a1177817979b1f6a59fc485 100644
index 1311d4936f84652c5ffc51544f99cb98fc293906..3a62831838a60776159dcb1ca783d3f00e6cd35e 100644
--- a/net/minecraft/world/Containers.java
+++ b/net/minecraft/world/Containers.java
@@ -51,4 +51,15 @@ public class Containers {
@@ -51,4 +51,16 @@ public class Containers {
public static void updateNeighboursAfterDestroy(final BlockState state, final Level level, final BlockPos pos) {
level.updateNeighbourForOutputSignal(pos, state.getBlock());
}
+
+
+ // Leaves start - behaviour 1.21.1-
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
+ if (!state.is(newState.getBlock())) {
@@ -28,10 +29,10 @@ index 1311d4936f84652c5ffc51544f99cb98fc293906..b4cbe16c9660f3e88a1177817979b1f6
+ // Leaves end - behaviour 1.21.1-
}
diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
index 98561dcc465ca9d5394e58b05ad3e8dc59773ebc..16b9f7eaccbe63aa13fcc89571e0b9c95ff9fd25 100644
index 98561dcc465ca9d5394e58b05ad3e8dc59773ebc..72e3d6c1ce3389972df21d5ff6e4d74bcf2ad300 100644
--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java
+++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
@@ -53,6 +53,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
@@ -53,6 +53,27 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
@@ -54,15 +55,16 @@ index 98561dcc465ca9d5394e58b05ad3e8dc59773ebc..16b9f7eaccbe63aa13fcc89571e0b9c9
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
index 5332fd32fa7a0d3fc3be1b0a7c2ca5dee8e402c6..0a77f67da73856edd2c45c8a9c6962cc653d7176 100644
index 5332fd32fa7a0d3fc3be1b0a7c2ca5dee8e402c6..37667a8e512bdba385c563e950d8c5d5cdd18832 100644
--- a/net/minecraft/world/level/block/BarrelBlock.java
+++ b/net/minecraft/world/level/block/BarrelBlock.java
@@ -51,6 +51,14 @@ public class BarrelBlock extends BaseEntityBlock {
@@ -51,6 +51,15 @@ public class BarrelBlock extends BaseEntityBlock {
return InteractionResult.SUCCESS;
}
@@ -73,15 +75,16 @@ index 5332fd32fa7a0d3fc3be1b0a7c2ca5dee8e402c6..0a77f67da73856edd2c45c8a9c6962cc
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
index c2fbf44e93e44c36423465d406b5e4d3db029a80..e22cade1f4258f9660f1f5ac3a330432cdf326d1 100644
index c2fbf44e93e44c36423465d406b5e4d3db029a80..a28a453f139295834c77aa908027c74c8dfd7aba 100644
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
@@ -133,6 +133,19 @@ public abstract class BasePressurePlateBlock extends Block {
@@ -133,6 +133,20 @@ public abstract class BasePressurePlateBlock extends Block {
}
}
@@ -97,15 +100,16 @@ index c2fbf44e93e44c36423465d406b5e4d3db029a80..e22cade1f4258f9660f1f5ac3a330432
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && this.getSignalForState(state) > 0) {
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
index bc79a7c2cb18237dad15432ae7e1238125108696..ac1db4712de6d998fe6b992dd75ed5f7fd1a0338 100644
index bc79a7c2cb18237dad15432ae7e1238125108696..5ef16955c69f0e0fecc772067a0fb006e6413011 100644
--- a/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
@@ -123,6 +123,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
@@ -123,6 +123,24 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
}
}
@@ -125,19 +129,19 @@ index bc79a7c2cb18237dad15432ae7e1238125108696..ac1db4712de6d998fe6b992dd75ed5f7
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
index aea12aad3270b966eed7779eaf77d26052f8a21f..751792a388202a14be69fd68f891198bcea71193 100644
index aea12aad3270b966eed7779eaf77d26052f8a21f..6c39edf98f33df437880a77450557082ea9b0f6c 100644
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
@@ -79,7 +79,13 @@ public class BrewingStandBlock extends BaseEntityBlock {
double z = pos.getZ() + 0.4 + random.nextFloat() * 0.2;
@@ -80,6 +80,15 @@ public class BrewingStandBlock extends BaseEntityBlock {
level.addParticle(ParticleTypes.SMOKE, x, y, z, 0.0, 0.0, 0.0);
}
-
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
@@ -145,14 +149,16 @@ index aea12aad3270b966eed7779eaf77d26052f8a21f..751792a388202a14be69fd68f891198b
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
index 86f4dcd959bb83247c6d2c5e947c79230aed3189..e6c2630e33ac23b31a01ef8b1c5c10b72a854251 100644
index 86f4dcd959bb83247c6d2c5e947c79230aed3189..1b0223f1d533d1a8db5497ab9104052bc799f691 100644
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -131,6 +131,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
@@ -131,6 +131,20 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
return pressed ? this.type.buttonClickOn() : this.type.buttonClickOff();
}
@@ -168,15 +174,16 @@ index 86f4dcd959bb83247c6d2c5e947c79230aed3189..e6c2630e33ac23b31a01ef8b1c5c10b7
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
index 8b706b34914326c039b761387f25e488f30fe6c8..d83754699a181c6abb97e9492186dc96d922b325 100644
index 8b706b34914326c039b761387f25e488f30fe6c8..b816594fcd83d26037734ec051f2c5d7f7dbde9f 100644
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -111,6 +111,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
@@ -111,6 +111,21 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
@@ -193,15 +200,16 @@ index 8b706b34914326c039b761387f25e488f30fe6c8..d83754699a181c6abb97e9492186dc96
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void entityInside(
final BlockState state,
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
index d3f0680d59ec87990b54dc3dbce27706bfadf5f1..85d6c53c06245d5692d27650fc5b5f98f4760dfc 100644
index d3f0680d59ec87990b54dc3dbce27706bfadf5f1..b5595d87339e4d313c5691a06c2b1b3d1b40b6de 100644
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -257,6 +257,14 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
@@ -257,6 +257,15 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
return this.chestCanConnectTo(state) && state.getValue(TYPE) == ChestType.SINGLE ? state.getValue(FACING) : null;
}
@@ -212,15 +220,16 @@ index d3f0680d59ec87990b54dc3dbce27706bfadf5f1..85d6c53c06245d5692d27650fc5b5f98
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
index 0682acaae12650549eea3c291d8cde7bb17766bd..9dc7edb546eafc60c05f9004205f1ff329c6a46b 100644
index 0682acaae12650549eea3c291d8cde7bb17766bd..ac12ef0c99c82d771e5275ec7ced7f76c76f5938 100644
--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
@@ -168,6 +168,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl
@@ -168,6 +168,28 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
}
@@ -244,15 +253,16 @@ index 0682acaae12650549eea3c291d8cde7bb17766bd..9dc7edb546eafc60c05f9004205f1ff3
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
index 2b97fd6af1c4956eb173b8c66c2a3efc8772a798..8f7258e3cb01ae55fd153b051506b54c2db91782 100644
index 2b97fd6af1c4956eb173b8c66c2a3efc8772a798..90326fe95673edbf5ed8c1a5d9020735fdd4d53e 100644
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -130,6 +130,14 @@ public class CrafterBlock extends BaseEntityBlock {
@@ -130,6 +130,15 @@ public class CrafterBlock extends BaseEntityBlock {
}
}
@@ -263,15 +273,16 @@ index 2b97fd6af1c4956eb173b8c66c2a3efc8772a798..8f7258e3cb01ae55fd153b051506b54c
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
index 3dd5f8c20ad68e0bd6222c8ba1687df0b2ad3b0d..746f140ea7522db879b8af1922be54395741c9f2 100644
index 3dd5f8c20ad68e0bd6222c8ba1687df0b2ad3b0d..b2e1e78cd70e20dd1c17ef0199059fc2b4e513b5 100644
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
@@ -152,6 +152,17 @@ public class CreakingHeartBlock extends BaseEntityBlock {
builder.add(AXIS, STATE, NATURAL);
}
@@ -284,15 +295,16 @@ index 3dd5f8c20ad68e0bd6222c8ba1687df0b2ad3b0d..746f140ea7522db879b8af1922be5439
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
index 3ce41ce3f9d2bf7a79e4b9811e043a69e0dedb13..237d0f609a9343ea067fe0bbe4a80dc9a61d8eff 100644
index 3ce41ce3f9d2bf7a79e4b9811e043a69e0dedb13..2856b4081cddb38bac5c1d7199649a7531ef077f 100644
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -172,6 +172,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
@@ -172,6 +172,15 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
return new DecoratedPotBlockEntity(worldPosition, blockState);
}
@@ -303,15 +315,16 @@ index 3ce41ce3f9d2bf7a79e4b9811e043a69e0dedb13..237d0f609a9343ea067fe0bbe4a80dc9
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
index 3457a1fa8f5efc4bf173bf155165ab5e5ae9f303..fc1861cffed656ecb0f58e5aef11f85cc40c7785 100644
index 3457a1fa8f5efc4bf173bf155165ab5e5ae9f303..1342607e3bf28ca085f51ade22efaf34f19da170 100644
--- a/net/minecraft/world/level/block/DiodeBlock.java
+++ b/net/minecraft/world/level/block/DiodeBlock.java
@@ -180,6 +180,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
@@ -180,6 +180,17 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
}
@@ -324,15 +337,16 @@ index 3457a1fa8f5efc4bf173bf155165ab5e5ae9f303..fc1861cffed656ecb0f58e5aef11f85c
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
index dca954bd076fa917512af91e0b93d449eb5cac6d..6e52b01c497357ebd51f319b9d9e3eec2e52a069 100644
index dca954bd076fa917512af91e0b93d449eb5cac6d..7f880ba7cdd08be392dd4fe5a06fffbf6962318b 100644
--- a/net/minecraft/world/level/block/DispenserBlock.java
+++ b/net/minecraft/world/level/block/DispenserBlock.java
@@ -159,6 +159,14 @@ public class DispenserBlock extends BaseEntityBlock {
@@ -159,6 +159,15 @@ public class DispenserBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
}
@@ -343,15 +357,16 @@ index dca954bd076fa917512af91e0b93d449eb5cac6d..6e52b01c497357ebd51f319b9d9e3eec
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
index 88606b84ea3a33ffbb0cfa6e073eb8f59d7188d0..413be2cbaf2ca89974f3f6242d6a3499e70fb018 100644
index 88606b84ea3a33ffbb0cfa6e073eb8f59d7188d0..c3ccebd7f27fd4d313cbcd616d58180a70f5f574 100644
--- a/net/minecraft/world/level/block/HopperBlock.java
+++ b/net/minecraft/world/level/block/HopperBlock.java
@@ -139,6 +139,14 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
@@ -139,6 +139,15 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
}
}
@@ -362,15 +377,16 @@ index 88606b84ea3a33ffbb0cfa6e073eb8f59d7188d0..413be2cbaf2ca89974f3f6242d6a3499
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
index a9e46a66ffc868c3b4ef2bb6257f23a20f12b1a6..8f32082ccc49b50d9a1d1048841342ce3817a36f 100644
index a9e46a66ffc868c3b4ef2bb6257f23a20f12b1a6..cee96a825f0e0e740ede8df0bf6dc5256b9fb8d3 100644
--- a/net/minecraft/world/level/block/JukeboxBlock.java
+++ b/net/minecraft/world/level/block/JukeboxBlock.java
@@ -82,6 +82,19 @@ public class JukeboxBlock extends BaseEntityBlock {
@@ -82,6 +82,20 @@ public class JukeboxBlock extends BaseEntityBlock {
}
}
@@ -386,15 +402,16 @@ index a9e46a66ffc868c3b4ef2bb6257f23a20f12b1a6..8f32082ccc49b50d9a1d1048841342ce
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
index 75660fb19c25444e35dbbe58cd20f9b3d3f7ad32..7d4ce2d8018e7be813e32a462ee4c33872f9bb4a 100644
index 75660fb19c25444e35dbbe58cd20f9b3d3f7ad32..196051c80baa489f43065a11a61f22a8c61251e7 100644
--- a/net/minecraft/world/level/block/LecternBlock.java
+++ b/net/minecraft/world/level/block/LecternBlock.java
@@ -200,6 +200,36 @@ public class LecternBlock extends BaseEntityBlock {
@@ -200,6 +200,37 @@ public class LecternBlock extends BaseEntityBlock {
changePowered(level, pos, state, false);
}
@@ -427,15 +444,16 @@ index 75660fb19c25444e35dbbe58cd20f9b3d3f7ad32..7d4ce2d8018e7be813e32a462ee4c338
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
index 341960ef67a689f660d0dcf61aaf5bf52bdc9074..341acc65fb2ffa45d9ad90fa15cf4e972e68a95e 100644
index 341960ef67a689f660d0dcf61aaf5bf52bdc9074..6fc372e782f2a34a34a9ef1faed41ace6db5ec1b 100644
--- a/net/minecraft/world/level/block/LeverBlock.java
+++ b/net/minecraft/world/level/block/LeverBlock.java
@@ -127,6 +127,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
@@ -127,6 +127,20 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
}
}
@@ -451,15 +469,16 @@ index 341960ef67a689f660d0dcf61aaf5bf52bdc9074..341acc65fb2ffa45d9ad90fa15cf4e97
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
index 47ca45518df306cc4368983eefb89294e56b015a..c440a04864fae43f94185e02bb8c3c33abf01a5c 100644
index 47ca45518df306cc4368983eefb89294e56b015a..31be8864aa28eff804b507efdab614b35e3fea6f 100644
--- a/net/minecraft/world/level/block/LightningRodBlock.java
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
@@ -123,6 +123,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
@@ -123,6 +123,19 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
}
}
@@ -474,15 +493,16 @@ index 47ca45518df306cc4368983eefb89294e56b015a..c440a04864fae43f94185e02bb8c3c33
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
index 6a3413ca875ce78f48cd8d3ce2cfe7798be1a19e..c492a770cedf976949434d700c943fcd8d4b4199 100644
index 6a3413ca875ce78f48cd8d3ce2cfe7798be1a19e..be572eff561ffdd961a9602eaa6136761c4d48a4 100644
--- a/net/minecraft/world/level/block/ObserverBlock.java
+++ b/net/minecraft/world/level/block/ObserverBlock.java
@@ -128,6 +128,17 @@ public class ObserverBlock extends DirectionalBlock {
@@ -128,6 +128,18 @@ public class ObserverBlock extends DirectionalBlock {
}
}
@@ -496,15 +516,16 @@ index 6a3413ca875ce78f48cd8d3ce2cfe7798be1a19e..c492a770cedf976949434d700c943fcd
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 66a05f099a263b0c9220f1416f3cf1221422cc20..eb7b8d971185764230d575af1f54537b48526548 100644
index 619f5e37919693fc5976aedefed3bb5428395439..ed190e16df7c6b80fd90561e7c2fdd53c745e54a 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -378,6 +378,27 @@ public class RedStoneWireBlock extends Block {
@@ -378,6 +378,28 @@ public class RedStoneWireBlock extends Block {
}
}
@@ -528,15 +549,16 @@ index 66a05f099a263b0c9220f1416f3cf1221422cc20..eb7b8d971185764230d575af1f54537b
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
index 0d0b5443c5c56825e88fd64c02c993eca6044d45..23137a24794fbe1536e1c47bc783ed211fc1042f 100644
index 0d0b5443c5c56825e88fd64c02c993eca6044d45..e2e5552008547fa1782b0a5ed3129162e94647c9 100644
--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java
+++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java
@@ -54,6 +54,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
@@ -54,6 +54,16 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
}
}
@@ -548,15 +570,16 @@ index 0d0b5443c5c56825e88fd64c02c993eca6044d45..23137a24794fbe1536e1c47bc783ed21
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
index 2bbce50d9dd0ca65f9e3bc90c8de098473039bc5..94ec05d2c6338464f4912cc1c919165c080f8cde 100644
index 2bbce50d9dd0ca65f9e3bc90c8de098473039bc5..9a9fcb593c4b5f2bb0c57f9268dfdc9eb21d38ea 100644
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -129,6 +129,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
@@ -129,6 +129,19 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
}
}
@@ -571,15 +594,16 @@ index 2bbce50d9dd0ca65f9e3bc90c8de098473039bc5..94ec05d2c6338464f4912cc1c919165c
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
index d7e5ec23c64b60c47ab6b54cbf282e88c3a4a045..6858d2721a7e5bad21756bacd90255e3c817f931 100644
index d7e5ec23c64b60c47ab6b54cbf282e88c3a4a045..037aa3592a963bbb142465d31040f60e95cb146e 100644
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
@@ -68,6 +68,17 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
super.stepOn(level, pos, onState, entity);
}
@@ -592,15 +616,16 @@ index d7e5ec23c64b60c47ab6b54cbf282e88c3a4a045..6858d2721a7e5bad21756bacd90255e3
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void tick(final BlockState state, final ServerLevel level, final BlockPos pos, final RandomSource random) {
if (state.getValue(SHRIEKING)) {
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index ffa76dc1338c6c892a42b2148f9f01c933660b98..2957008ce8fc8c39a7c13637dad42784f230f575 100644
index 8259f530ec50554906c254b60f1e964b52c02852..59ad645785bc99758f4bc124c56e39d87c4b75c2 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -150,6 +150,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -150,6 +150,20 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
// Paper end - re-set loot table if it was cleared
}
@@ -616,39 +641,38 @@ index ffa76dc1338c6c892a42b2148f9f01c933660b98..2957008ce8fc8c39a7c13637dad42784
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
index 04e5995409a3532947dfab1c8ef05bd546a6f66d..961995694172658716309e2695f9a034fe058b06 100644
index 04e5995409a3532947dfab1c8ef05bd546a6f66d..6bf811477a27bbbeeeba6c9d768d33fc677ea5e7 100644
--- a/net/minecraft/world/level/block/TripWireBlock.java
+++ b/net/minecraft/world/level/block/TripWireBlock.java
@@ -107,9 +107,18 @@ public class TripWireBlock extends Block {
@@ -107,6 +107,17 @@ public class TripWireBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
@Override
- protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
+ if (!isMoving && !state.is(newState.getBlock())) {
+ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE));
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+ @Override
+ protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
this.updateSource(level, pos, state.setValue(POWERED, true));
}
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
index fd808353181e05f2fc527a391ce7bb990f61b4c7..e070b2781ce15c754a678eb76de4c0248b0ddec7 100644
index fd808353181e05f2fc527a391ce7bb990f61b4c7..836eae0c3e0891a3e3309b684f15d65f891215cf 100644
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -248,6 +248,25 @@ public class TripWireHookBlock extends Block {
@@ -248,6 +248,26 @@ public class TripWireHookBlock extends Block {
level.updateNeighborsAt(pos.relative(front), block, orientation);
}
@@ -670,6 +694,7 @@ index fd808353181e05f2fc527a391ce7bb990f61b4c7..e070b2781ce15c754a678eb76de4c024
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
@@ -688,10 +713,10 @@ index ac58bbed01edaf5dfe4839c89649ca865c339c8a..caead1012ff3b5b5f78c24a3baf20b7d
@Deprecated
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index 2b6ad989e1e1424d0283bae39e5dae33eba44923..c72a14a8c3d9fe4430cfde671f29688c696f983a 100644
index 2b6ad989e1e1424d0283bae39e5dae33eba44923..0f47fb528422d591bd03434a089ea69c7f27bf8c 100644
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -70,6 +70,18 @@ public class MovingPistonBlock extends BaseEntityBlock {
@@ -70,6 +70,19 @@ public class MovingPistonBlock extends BaseEntityBlock {
return createTickerHelper(type, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
}
@@ -706,15 +731,16 @@ index 2b6ad989e1e1424d0283bae39e5dae33eba44923..c72a14a8c3d9fe4430cfde671f29688c
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
public void destroy(final LevelAccessor level, final BlockPos pos, final BlockState state) {
BlockPos relative = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index f8caa0b3c21766dbad73c524c1680346e4257188..343660d3e5fbdc25aba84a5cacbc367d40533848 100644
index f8caa0b3c21766dbad73c524c1680346e4257188..b658d602953ade618d89c02745eb46be5d0175dd 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
@@ -78,6 +78,20 @@ public class PistonHeadBlock extends DirectionalBlock {
return super.playerWillDestroy(level, pos, state, player);
}
@@ -730,15 +756,16 @@ index f8caa0b3c21766dbad73c524c1680346e4257188..343660d3e5fbdc25aba84a5cacbc367d
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
BlockPos basePos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 0fbdf810c785c8a596d461e7651361fdedbb6217..66f3fbe18451644be939b22342fc22592005d252 100644
index 0fbdf810c785c8a596d461e7651361fdedbb6217..ff1471f40b73582df68efbf2996a854c6aa37d65 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -174,6 +174,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
@@ -174,6 +174,16 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
}
@@ -750,11 +777,12 @@ index 0fbdf810c785c8a596d461e7651361fdedbb6217..66f3fbe18451644be939b22342fc2259
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
}
@@ -889,6 +898,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
@@ -889,6 +899,13 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
// CraftBukkit end
}
@@ -763,15 +791,16 @@ index 0fbdf810c785c8a596d461e7651361fdedbb6217..66f3fbe18451644be939b22342fc2259
+ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
public void affectNeighborsAfterRemoval(final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index b7ba4d8ed2cc65ba0e85a3cdf8b6568a7c9c02f1..6b5ad391eda92cdbb47ab78a4c27d7e6a3b098a8 100644
index ef3508dc4c8b3a9c8a6c7ff520cf51a68d6a13d9..11f0f5e1b8ee9ce7e6833d46ccb557d896674431 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -408,22 +408,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -423,22 +423,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
boolean blockChanged = !oldState.is(newBlock);
boolean movedByPiston = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0;
boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Wed, 3 Jun 2026 02:20:00 +0800
Subject: [PATCH] MiniTweaks mob fire and explosion rules
diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java
index 5005f2b923aa94dbc38fb75d5b6f58344888c895..0d4ba81c82b683c32addf6441de3843abf462c3c 100644
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -250,7 +250,8 @@ public class Creeper extends Monster {
if (!event.isCancelled()) {
// CraftBukkit end
this.dead = true;
- level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
+ Level.ExplosionInteraction explosionInteraction = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.noCreeperBlockBreaking ? Level.ExplosionInteraction.NONE : Level.ExplosionInteraction.MOB; // Lophine - MiniTweaks noCreeperBlockBreaking
+ level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), explosionInteraction); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(level, Entity.RemovalReason.KILLED);
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
diff --git a/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java b/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
index 711b97aa9e49b7edee34c91d77b1005be4fa96bd..1d9232c9061bde9c545e3ee25bc9c6b0417b9ece 100644
--- a/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
+++ b/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
@@ -37,7 +37,9 @@ public class LargeFireball extends Fireball {
// CraftBukkit start - fire ExplosionPrimeEvent
org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
if (event.callEvent()) {
- this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
+ Level.ExplosionInteraction explosionInteraction = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.noGhastBlockBreaking ? Level.ExplosionInteraction.NONE : Level.ExplosionInteraction.MOB; // Lophine - MiniTweaks noGhastBlockBreaking
+ boolean createFire = event.getFire() && !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.disableGhastFire; // Lophine - MiniTweaks disableGhastFire
+ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), createFire, explosionInteraction);
}
// CraftBukkit end - fire ExplosionPrimeEvent
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
diff --git a/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java b/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
index 1a72ee1559f75660796a9cbc1a9d9cdd6883dc90..480042d9401b6d7618fc2f36f16145606414d475 100644
--- a/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
+++ b/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
@@ -63,7 +63,7 @@ public class SmallFireball extends Fireball {
super.onHitBlock(hitResult);
if (this.level() instanceof ServerLevel serverLevel) {
Entity owner = this.getOwner();
- if (this.isIncendiary) { // CraftBukkit
+ if (this.isIncendiary && (!(owner instanceof Mob) || !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.disableBlazeFire)) { // CraftBukkit // Lophine - MiniTweaks disableBlazeFire
BlockPos pos = hitResult.getBlockPos().relative(hitResult.getDirection());
if (this.level().isEmptyBlock(pos) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), pos, this).isCancelled()) { // CraftBukkit
this.level().setBlockAndUpdate(pos, BaseFireBlock.getState(this.level(), pos));
@@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Carpet Features Compatible
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 8b05860d2787a40495f8a025bc0bc43789d6a6af..2ef6a7fb5a9c3452dfff70a67542e2ca2531c897 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -340,7 +340,7 @@ public final class RegionizedServer {
final long tickStartNanos = System.nanoTime();
++this.tickCount;
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
MinecraftServer.getServer().tickRateManager().tick();
}
// Luminol end - Add a config to enable tick command
@@ -529,7 +529,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final long tickCount) {
- if ((!me.earthme.luminol.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
+ if ((!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command // Lophine - redirect
world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + tickCount);
}
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 917d6965e91527fc79d545c041765f78a357eac2..19ddbee489e9b17ef0bf794fa6cc3c10cc0ed565 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -595,7 +595,7 @@ public final class TickRegionScheduler {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
MinecraftServer.getServer().tickRateManager().endTickWork();
}
// Luminol end - Add a config to enable tick command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index bb5059a77741bf1d9e73bd8c7f0da6681ec63f67..270ee3c01ad0b351bee068a507b09a9d0041ae9c 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -266,7 +266,7 @@ public class Commands {
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
}
// Luminol end - Add a config to enable tick command
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 5ebff729bb7e75e1c84449c0e3021b972ad0d936..d35cc60b1f4a59ab1b74da5d8d55d63c94a9055b 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2186,7 +2186,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.lastSentFood = -1;
this.teleportSpectators(transition, oldLevel);
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
}
// Leaves end - bot support
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index baa295f3dd8cf10bf7347ee4d1c249b1f82c9279..1d5376650d0f5eeb23fde8d7116b47cfae37576f 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -280,7 +280,7 @@ public abstract class PlayerList {
// org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
if (bot != null) {
this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -441,7 +441,7 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
if (bot != null) {
this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -969,7 +969,7 @@ public abstract class PlayerList {
).callEvent();
// Paper end
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
}
// Leaves end - bot support
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 3e4fae7a5ae7f8a26bf78727e81c4a87e8fed332..1340ef0ba7660a0e3c4cce105a90fcc4eadcf559 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -240,7 +240,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
// Leaves start - Wool hopper counter
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, entity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
if (woolColor != null) {
for (int i = 0; i < Short.MAX_VALUE; i++) {
@@ -258,7 +258,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (changed) {
entity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
// Leaves start - Wool hopper counter
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
entity.setCooldown(0);
return true;
}
@@ -664,7 +664,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static boolean addItem(final Container container, final ItemEntity entity) {
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && entity.isRemoved()) return false; // Leaves - Wool hopper counter
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && entity.isRemoved()) return false; // Leaves - Wool hopper counter
boolean changed = false;
// CraftBukkit start
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
diff --git a/net/minecraft/world/level/dimension/end/EnderDragonFight.java b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
index 5ca008b3dca83c00f2ae86a608d726972a8d9f9d..4274f22710035b547f5aca617c80c5c99f3a4dc8 100644
--- a/net/minecraft/world/level/dimension/end/EnderDragonFight.java
+++ b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
@@ -323,7 +323,7 @@ public class EnderDragonFight extends SavedData {
private int cachePortalOriginIteratorY = -1;
public BlockPattern.@Nullable BlockPatternMatch findExitPortal() {
- if (me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig.optimizedRespawn) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.optimizedDragonRespawn) {
int i, j;
for (i = cachePortalChunkIteratorX; i <= 8; ++i) {
for (j = cachePortalChunkIteratorZ; j <= 8; ++j) {
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e7f4a313ff0d2469
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 20bebf72768968d90f27f812456796cf81f46626..479bbc4a63c237c055f6b4d659c598e9fadd512a 100644
index ba0779211405b8b83f7c7e7b1c55b3e4846029a3..5f685b07878443bfe5f63147a0728df0708d79ad 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -483,6 +483,7 @@ public final class CraftServer implements Server {
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
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 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6f9f62263 100644
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..d0b763f07aee56f69a67c87d7dd15a44b6f44db7 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -36,6 +36,15 @@ class PaperEventManager {
@@ -16,7 +16,7 @@ index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6
// SimplePluginManager
public void callEvent(@NotNull Event event) {
+ // Leaves start - process bot load/save
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable && fun.bm.lophine.config.modules.function.FakeplayerConfig.canResident) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled() && fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig.fakePlayerResident) {
+ if (event instanceof org.bukkit.event.world.WorldLoadEvent worldLoadEvent) {
+ org.leavesmc.leaves.bot.BotList.INSTANCE.loadResume(worldLoadEvent.getWorld().getUID().toString());
+ } else if (event instanceof org.bukkit.event.world.WorldUnloadEvent worldUnloadEvent) {
@@ -53,7 +53,7 @@ index 5339ff469a38d35e72ea7227503a84395462f84a..d75b4ecb24f2ea42afc82ac255775d8f
if (nmsEntity.level() != this.getHandle().getLevel()) {
throw new IllegalArgumentException(entity + " wasn't created with this world, you must create the entity with the world you want to add it to.");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 479bbc4a63c237c055f6b4d659c598e9fadd512a..054d9f4a09035771a329d6d561249d206b5dbee3 100644
index 5f685b07878443bfe5f63147a0728df0708d79ad..0eb89fc127738e02e8d4d49418b83baaffe00cbd 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -303,6 +303,7 @@ public final class CraftServer implements Server {
@@ -81,7 +81,7 @@ index 479bbc4a63c237c055f6b4d659c598e9fadd512a..054d9f4a09035771a329d6d561249d20
return false;
}
@@ -3055,6 +3057,13 @@ public final class CraftServer implements Server {
@@ -3113,6 +3115,13 @@ public final class CraftServer implements Server {
}
// Leaves end - Feature API
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
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 e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 100644
index d0b763f07aee56f69a67c87d7dd15a44b6f44db7..bd301425f4c3cdf2b2bd22c1775b7ca9be1d4248 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -57,7 +57,7 @@ class PaperEventManager {
@@ -21,7 +21,7 @@ index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9de
}
// Leaves end - skip bot
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 054d9f4a09035771a329d6d561249d206b5dbee3..8fc75ef37f273433fb11cc1e0beee87484c3e18f 100644
index 0eb89fc127738e02e8d4d49418b83baaffe00cbd..53e49df883ec0fab984f2329d044d12ed6b1edff 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -304,6 +304,7 @@ public final class CraftServer implements Server {
@@ -41,7 +41,7 @@ index 054d9f4a09035771a329d6d561249d206b5dbee3..8fc75ef37f273433fb11cc1e0beee874
@Override
public CraftPlayer apply(ServerPlayer player) {
return player.getBukkitEntity();
@@ -3128,4 +3129,11 @@ public final class CraftServer implements Server {
@@ -3186,4 +3187,11 @@ public final class CraftServer implements Server {
}
}
// Folia end - region TPS API
@@ -1,20 +1,10 @@
/*
package fun.bm.lophine.carpet;
import fun.bm.lophine.carpet.config.modules.CoreConfig;
import fun.bm.lophine.carpet.config.modules.CounterCompatConfig;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
import fun.bm.lophine.config.modules.experiment.CommandConfig;
import fun.bm.lophine.config.modules.experiment.RedStoneConfig;
import fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig;
import fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig;
import fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import fun.bm.lophine.config.modules.function.LanguageConfig;
import fun.bm.lophine.config.modules.function.WoolHopperCounterConfig;
import fun.bm.lophine.protocol.CarpetLoggerProtocol;
import me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
import java.util.List;
@@ -24,42 +14,11 @@ public final class CarpetCompatSync {
private static boolean init = false;
public static void apply() {
if (init) return;
if (CoreConfig.enabled) {
applyGeneralRules();
applyFakePlayerRules();
applyCounterRules();
}
CarpetLoggerProtocol.refreshConfiguredDefaults(!init);
registerProtocolRules();
init = true;
}
private static void applyGeneralRules() {
LanguageConfig.lang = GeneralCompatConfig.language;
UpdateSuppressionCrashFixConfig.enabled = GeneralCompatConfig.amsUpdateSuppressionCrashFix || GeneralCompatConfig.yeetUpdateSuppressionCrash;
RedStoneConfig.redstoneIgnoreUpwardsUpdate = GeneralCompatConfig.dustTrapdoorReintroduced;
RedStoneConfig.cce = GeneralCompatConfig.shulkerBoxCCEReintroduced;
RedStoneConfig.instantBlockUpdater = GeneralCompatConfig.instantBlockUpdaterReintroduced;
CommandConfig.tick = GeneralCompatConfig.commandTick;
CreativeFlyNoClipConfig.enabled = GeneralCompatConfig.creativeNoClip;
OptimizedDragonRespawnConfig.optimizedRespawn = GeneralCompatConfig.optimizedDragonRespawn;
}
private static void applyFakePlayerRules() {
FakeplayerConfig.enable = FakePlayerCompatConfig.commandBot || FakePlayerCompatConfig.commandPlayer;
FakeplayerConfig.canResident = FakePlayerCompatConfig.fakePlayerResident;
FakeplayerConfig.canOpenInventory = FakePlayerCompatConfig.openFakePlayerInventory;
FakeplayerConfig.tickType = FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer
? ServerBot.TickType.NETWORK
: ServerBot.TickType.ENTITY_LIST;
}
private static void applyCounterRules() {
WoolHopperCounterConfig.enabled = CounterCompatConfig.hopperCounters;
WoolHopperCounterConfig.unlimitedSpeed = CounterCompatConfig.hopperCountersUnlimitedSpeed;
}
private static List<String> sanitizeDefaultLoggers(List<String> configuredLoggers) {
return configuredLoggers == null ? List.of() : List.copyOf(configuredLoggers);
}
@@ -120,7 +79,7 @@ public final class CarpetCompatSync {
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntFuseDuration", GeneralCompatConfig.normalizedTntFuseDuration()));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "defaultLoggers", CarpetLoggerProtocol.serializeConfiguredDefaults(sanitizeDefaultLoggers(GeneralCompatConfig.defaultLoggers))));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "commandBot", FakePlayerCompatConfig.commandBot));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "commandBot", FakeplayerConfig.enable));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandPlayer", FakePlayerCompatConfig.commandPlayer));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerResident", FakePlayerCompatConfig.fakePlayerResident));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "openFakePlayerInventory", FakePlayerCompatConfig.openFakePlayerInventory));
@@ -133,8 +92,7 @@ public final class CarpetCompatSync {
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoFish", FakePlayerCompatConfig.fakePlayerAutoFish));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerReloadAction", FakePlayerCompatConfig.fakePlayerReloadAction));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "hopperCounters", CounterCompatConfig.hopperCounters));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", CounterCompatConfig.hopperCountersUnlimitedSpeed));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "hopperCounters", WoolHopperCounterConfig.hopperCounters));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", WoolHopperCounterConfig.hopperCountersUnlimitedSpeed));
}
}
*/
@@ -1,6 +1,8 @@
package fun.bm.lophine.carpet;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.mojang.logging.LogUtils;
import io.papermc.paper.threadedregions.RegionizedWorldData;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
@@ -24,9 +26,10 @@ import java.util.WeakHashMap;
public final class LagFreeSpawningCompatHelper {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Map<ServerLevel, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
private static final Map<RegionizedWorldData, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
public static boolean hasNoCollision(ServerLevel world, AABB bb) {
if (!TickThread.isTickThreadFor(world, bb)) return world.noCollision(bb);
int minX = Mth.floor(bb.minX);
int minY = Mth.floor(bb.minY);
int minZ = Mth.floor(bb.minZ);
@@ -84,15 +87,22 @@ public final class LagFreeSpawningCompatHelper {
}
public static @Nullable Mob getOrCreateMob(ServerLevel level, EntityType<?> entityType) {
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level, key -> new HashMap<>());
RegionizedWorldData data = level.getCurrentWorldData();
if (data == null) return createMob(level, entityType);
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level.getCurrentWorldData(), key -> new HashMap<>());
Mob mob = cache.get(entityType);
if (mob != null && !mob.isRemoved()) {
if (!TickThread.isTickThreadFor(mob)) return createMob(level, entityType);
return mob;
}
return createMob(level, entityType);
}
public static @Nullable Mob createMob(ServerLevel level, EntityType<?> entityType) {
try {
if (entityType.create(level, EntitySpawnReason.NATURAL) instanceof Mob created) {
cache.put(entityType, created);
PRECOOKED_MOBS.get(level.getCurrentWorldData()).put(entityType, created);
return created;
}
LOGGER.warn("Can't precook non-mob entity type: {}", entityType);
@@ -104,7 +114,7 @@ public final class LagFreeSpawningCompatHelper {
}
public static void markSpawned(ServerLevel level, EntityType<?> entityType) {
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level);
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level.getCurrentWorldData());
if (cache != null) {
cache.remove(entityType);
}
@@ -0,0 +1,162 @@
package fun.bm.lophine.carpet;
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
import fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import me.earthme.luminol.config.ConfigManager;
import me.earthme.luminol.config.ConfigsInstance;
public class RedirectedConfigs {
public static void redirect() {
updateSuppressionCrashFix();
commandTick();
optimizedDragonRespawn();
woolHopperCounter();
fakeplayer();
creativeFlyNoClip();
redstoneChanges();
}
private static void updateSuppressionCrashFix() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
try {
boolean updateSuppressionCrashFixEnabled = config.getConfigOrigin("fixes.update-suppression-crash-fix.enabled");
if (updateSuppressionCrashFixEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.amsUpdateSuppressionCrashFix = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "amsUpdateSuppressionCrashFix"}, true);
GeneralCompatConfig.yeetUpdateSuppressionCrash = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "yeetUpdateSuppressionCrash"}, true);
}
config.removeConfig(new String[]{"fixes", "update-suppression-crash-fix", "enabled"});
} catch (Exception ignored) {
}
}
private static void commandTick() {
try {
boolean shouldEnabled = false;
// first check lophine
try {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
shouldEnabled = config.getConfigOrigin("experiment.command.tick_command_enabled");
config.removeConfig(new String[]{"experiment", "command", "tick_command_enabled"});
} catch (Exception ignored) {
}
// then check luminol
try {
ConfigsInstance config = ConfigManager.getConfigs("luminol");
shouldEnabled = shouldEnabled || (boolean) config.getConfigOrigin("experiment.command.enable_tick_command");
config.removeConfig(new String[]{"experiment", "command", "enable_tick_command"});
} catch (Exception ignored) {
}
if (shouldEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.commandTick = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "commandTick"}, true);
}
} catch (Exception ignored) {
}
}
private static void optimizedDragonRespawn() {
ConfigsInstance config = ConfigManager.getConfigs("luminol");
try {
boolean optimizedDragonRespawnEnabled = config.getConfigOrigin("optimizations.end_dragon.optimized_dragon_respawn");
if (optimizedDragonRespawnEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.optimizedDragonRespawn = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "optimizedDragonRespawn"}, true);
}
config.removeConfig(new String[]{"optimizations", "end_dragon", "optimized_dragon_respawn"});
} catch (Exception ignored) {
}
}
private static void woolHopperCounter() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean woolHopperCounterEnabled = config.getConfigOrigin("function.wool-hopper-counter.enabled");
if (woolHopperCounterEnabled) {
WoolHopperCounterConfig.hopperCounters = true;
carpetConfig.setConfig(new String[]{"carpet", "hopper_counter", "hopperCounters"}, true);
}
config.removeConfig(new String[]{"function", "wool-hopper-counter", "enabled"});
} catch (Exception ignored) {
}
try {
boolean woolHopperCounterUnlimitedSpeed = config.getConfigOrigin("function.wool-hopper-counter.unlimited-speed");
if (woolHopperCounterUnlimitedSpeed) {
WoolHopperCounterConfig.hopperCountersUnlimitedSpeed = true;
carpetConfig.setConfig(new String[]{"carpet", "hopper_counter", "hopperCountersUnlimitedSpeed"}, true);
}
config.removeConfig(new String[]{"function", "wool-hopper-counter", "unlimited-speed"});
} catch (Exception ignored) {
}
}
private static void fakeplayer() {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean bot = carpetConfig.getConfigOrigin("carpet.fakeplayer.commandBot");
if (bot) {
try {
ConfigsInstance lophineConfig = ConfigManager.getConfigs("lophine");
FakeplayerConfig.enable = true;
lophineConfig.setConfig(new String[]{"function", "fakeplayer", "enable"}, true);
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
}
carpetConfig.removeConfig(new String[]{"carpet", "fakeplayer", "commandBot"});
}
private static void creativeFlyNoClip() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
try {
boolean creativeFlyNoClipEnabled = config.getConfigOrigin("function.creative_fly_no_clip.enabled");
if (creativeFlyNoClipEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.creativeNoClip = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "creativeNoClip"}, true);
}
config.removeConfig(new String[]{"function", "creative_fly_no_clip", "enabled"});
} catch (Exception ignored) {
}
}
private static void redstoneChanges() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean dustTrapdoorReintroduced = config.getConfigOrigin("experiment.redstone.redstone-ignore-upwards-update");
if (dustTrapdoorReintroduced) {
GeneralCompatConfig.dustTrapdoorReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "dustTrapdoorReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "redstone-ignore-upwards-update"});
} catch (Exception ignored) {
}
try {
boolean shulkerBoxCCEReintroduced = config.getConfigOrigin("experiment.redstone.cce-update-suppression");
if (shulkerBoxCCEReintroduced) {
GeneralCompatConfig.shulkerBoxCCEReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "shulkerBoxCCEReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "cce-update-suppression"});
} catch (Exception ignored) {
}
try {
boolean instantBlockUpdaterReintroduced = config.getConfigOrigin("experiment.redstone.instant-block-updater");
if (instantBlockUpdaterReintroduced) {
GeneralCompatConfig.instantBlockUpdaterReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "instantBlockUpdaterReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "instant-block-updater"});
} catch (Exception ignored) {
}
}
}
@@ -1,30 +0,0 @@
package fun.bm.lophine.carpet.config.modules;
//import fun.bm.lophine.carpet.CarpetCompatSync;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "core",
directory = {"carpet"}
)
public class CoreConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable carpet features.
If you want to use some function from Carpet modifier,
you need to enable it.
(some function is not managed by this option)
ONLY GENERAL DIRECTORY WAS CONTROLLED BY THIS OPTION.
WARNING: IF YOU ENABLED IT, ORIGINAL CONFIG IN LOPHINE CONFIG WILL BE OVERWRITTEN.""")
public static boolean enabled = false;
@Override
public void beforeFinalLoad() {
// CarpetCompatSync.apply();
}
}
@@ -1,24 +0,0 @@
package fun.bm.lophine.carpet.config.modules;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "hopper_counter",
directory = {"carpet"},
comments = """
Hopper counter compatibility mapped onto Lophine's wool hopper counter implementation."""
)
public class CounterCompatConfig implements IConfigModule {
@ConfigInfo(name = "hopperCounters", comments = """
Enable the existing wool hopper counter implementation.""")
public static boolean hopperCounters = false;
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
Remove the hopper transfer speed limit for counters.
Only effective when hopperCounters is enabled.""")
public static boolean hopperCountersUnlimitedSpeed = false;
}
@@ -1,9 +1,15 @@
package fun.bm.lophine.carpet.config.modules;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.command.bot.BotCommand;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
@@ -14,12 +20,9 @@ import me.earthme.luminol.enums.EnumConfigCategory;
commandPlayer is currently backed by Lophine's /bot command surface."""
)
public class FakePlayerCompatConfig implements IConfigModule {
@ConfigInfo(name = "commandBot", comments = """
Enable Lophine's /bot command.""")
public static boolean commandBot = false;
@ConfigInfo(name = "commandPlayer", comments = """
Map Carpet's commandPlayer rule to the same fakeplayer command surface used by /bot.""")
Enable /player command.(not remapped)
If you want to enable bot command, please see lophine global config.""")
public static boolean commandPlayer = false;
@ConfigInfo(name = "fakePlayerResident", comments = """
@@ -61,4 +64,23 @@ public class FakePlayerCompatConfig implements IConfigModule {
@ConfigInfo(name = "fakePlayerReloadAction", comments = """
Persist queued fakeplayer actions across save and reload.""")
public static boolean fakePlayerReloadAction = false;
@DoNotLoad
private BotCommand command = null;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (commandPlayer) {
command = new BotCommand("player");
command.register();
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (command != null) {
command.unregister();
command = null;
}
}
}
@@ -1,8 +1,11 @@
package fun.bm.lophine.carpet.config.modules;
import fun.bm.lophine.carpet.CarpetCompatSync;
import fun.bm.lophine.carpet.RedirectedConfigs;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@@ -16,40 +19,47 @@ import java.util.List;
Only rules that already have a working server-side implementation are exposed here."""
)
public class GeneralCompatConfig implements IConfigModule {
@TransformedConfig(name = "language", directory = {"carpet", "general"}, transformComments = false)
@ConfigInfo(name = "language", comments = """
Carpet language value forwarded to lophine.function.language.lang.""")
Carpet language value.
ATTENTION: This config will not update in Lophine global now!""")
public static String language = "en_us";
@ConfigInfo(name = "amsUpdateSuppressionCrashFix", comments = """
Map AMS update suppression crash protection to Lophine's existing crash fix.""")
Update suppression crash protection.""")
public static boolean amsUpdateSuppressionCrashFix = false;
@ConfigInfo(name = "yeetUpdateSuppressionCrash", comments = """
Map TIS update suppression crash yeeting to the same Lophine crash fix.""")
Update suppression crash yeeting.""")
public static boolean yeetUpdateSuppressionCrash = false;
@ConfigInfo(name = "dustTrapdoorReintroduced", comments = """
Map dust-on-open-trapdoor behavior to Lophine's redstone-ignore-upwards-update option.""")
Should the pre-1.20 mechanism be reintroduced:
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters,
and redstone comparators do not check for attachment when receiving status updates from below.""")
public static boolean dustTrapdoorReintroduced = false;
@ConfigInfo(name = "shulkerBoxCCEReintroduced", comments = """
Map shulker-box CCE update suppression to Lophine's cce-update-suppression option.""")
Use ClassCastException for update suppression.""")
public static boolean shulkerBoxCCEReintroduced = false;
@ConfigInfo(name = "instantBlockUpdaterReintroduced", comments = """
Enable the existing instant block updater patch already carried by Lophine.""")
Instant block updater.""")
public static boolean instantBlockUpdaterReintroduced = false;
@ConfigInfo(name = "commandTick", comments = """
Enable the tick command support already patched into Lophine.""")
Enable the tick command support.""")
public static boolean commandTick = false;
@ConfigInfo(name = "creativeNoClip", comments = """
Enable the existing creative fly no clip implementation.""")
Whether to enable creative fly no clip.
When enabled, players in creative mode will not collide with blocks while flying.
This allows them to pass through blocks without obstruction.""")
public static boolean creativeNoClip = false;
@ConfigInfo(name = "optimizedDragonRespawn", comments = """
Enable the existing optimized dragon respawn implementation from Luminol.""")
Enable optimized dragon respawn.""")
public static boolean optimizedDragonRespawn = false;
@ConfigInfo(name = "antiSpamDisabled", comments = """
@@ -113,6 +123,22 @@ public class GeneralCompatConfig implements IConfigModule {
Let explosions damage entities without breaking blocks.""")
public static boolean explosionNoBlockDamage = false;
@ConfigInfo(name = "noCreeperBlockBreaking", comments = """
Disables creeper explosion block breaking.""")
public static boolean noCreeperBlockBreaking = false;
@ConfigInfo(name = "noGhastBlockBreaking", comments = """
Disables ghast fireball explosion block breaking.""")
public static boolean noGhastBlockBreaking = false;
@ConfigInfo(name = "disableBlazeFire", comments = """
Disables fire made from blaze fireballs.""")
public static boolean disableBlazeFire = false;
@ConfigInfo(name = "disableGhastFire", comments = """
Disables fire made from ghast fireballs.""")
public static boolean disableGhastFire = false;
@ConfigInfo(name = "optimizedTNTHighPriority", comments = """
Compatibility flag for the already optimized server explosion path carried by the current runtime.""")
public static boolean optimizedTNTHighPriority = false;
@@ -229,6 +255,10 @@ public class GeneralCompatConfig implements IConfigModule {
Examples: ["tps", "mob_caps", "counter white"]""")
public static List<String> defaultLoggers = List.of();
public static boolean mergedUpdateSuppressionCrashEnabled() {
return amsUpdateSuppressionCrashFix || yeetUpdateSuppressionCrash;
}
public static int normalizedTntFuseDuration() {
return Math.clamp(tntFuseDuration, 0, Short.MAX_VALUE);
}
@@ -236,4 +266,13 @@ public class GeneralCompatConfig implements IConfigModule {
public static int normalizedTickCommandPermission() {
return Math.clamp(tickCommandPermission, 0, 4);
}
@Override
public void beforeFinalLoad() {
// Should remove in next Minecraft version update
RedirectedConfigs.redirect();
// after all config updated, send changes to client
CarpetCompatSync.apply();
}
}
@@ -0,0 +1,16 @@
package fun.bm.lophine.carpet.config.modules;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"carpet", "core"})
@ConfigInfo(name = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
public static boolean enabled = true;
}
@@ -1,4 +1,4 @@
package fun.bm.lophine.config.modules.function;
package fun.bm.lophine.carpet.config.modules;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.command.counter.CounterCommand;
@@ -11,20 +11,29 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "hopper_counter",
directory = {"carpet"},
comments = """
Hopper counter functions."""
)
public class WoolHopperCounterConfig implements IConfigModule {
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "hopperCounters", comments = """
Enable the existing wool hopper counter implementation.""")
public static boolean hopperCounters = false;
@ConfigInfo(name = "unlimited-speed")
public static boolean unlimitedSpeed = false;
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
Remove the hopper transfer speed limit for counters.
Only effective when hopperCounters is enabled.""")
public static boolean hopperCountersUnlimitedSpeed = false;
@DoNotLoad
private static CounterCommand counterCommand = null;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enabled) {
if (hopperCounters) {
if (counterCommand == null) {
counterCommand = new CounterCommand();
}
@@ -7,10 +7,10 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "command")
public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "tick_command_enabled", comments =
@ConfigInfo(name = "trigger_command_enabled", comments =
"""
Allow to use tick command""")
public static boolean tick = false;
Allow to use trigger command""")
public static boolean trigger = false;
@ConfigInfo(name = "function_command_enabled", comments =
"""
@@ -3,8 +3,6 @@ package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
/*
@@ -13,19 +11,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
*/
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@ConfigInfo(name = "redstone-ignore-upwards-update", comments = """
Should the pre-1.20 mechanism be reintroduced:
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters, and redstone comparators do not check for attachment when receiving status updates from below""")
public static boolean redstoneIgnoreUpwardsUpdate = false;
@ConfigInfo(name = "cce-update-suppression", comments = """
Is it permissible to use ClassCastException for update suppression?""")
public static boolean cce = false;
@HotReloadUnsupported
@ConfigInfo(name = "instant-block-updater")
public static boolean instantBlockUpdater = false;
@ConfigInfo(name = "old-block-remove-behaviour")
public static boolean oldBlockRemoveBehaviour = false;
@@ -1,25 +0,0 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
import java.util.Set;
@ConfigClassInfo(name = "creative_fly_no_clip", category = EnumConfigCategory.FUNCTION)
public class CreativeFlyNoClipConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Whether to enable creative fly no clip.
When enabled, players in creative mode will not collide with blocks while flying.
This allows them to pass through blocks without obstruction.""")
public static boolean enabled = false;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "creativeNoClip", enabled));
}
}
@@ -1,9 +1,11 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
@@ -15,7 +17,7 @@ import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(name = "enable", comments = """
Enable fakeplayer functionality""")
Enable fakeplayer functionality (/bot command)""")
public static boolean enable = true;
@ConfigInfo(name = "unable-fakeplayer-names", comments = """
@@ -38,14 +40,6 @@ public class FakeplayerConfig implements IConfigModule {
Regeneration amount for fakeplayers""")
public static double regenAmount = 0.0;
@ConfigInfo(name = "resident-fakeplayer", comments = """
Allow fakeplayers to be resident""")
public static boolean canResident = false;
@ConfigInfo(name = "open-fakeplayer-inventory", comments = """
Allow opening fakeplayer inventory""")
public static boolean canOpenInventory = false;
@ConfigInfo(name = "use-action", comments = """
Allow fakeplayers to use actions""")
public static boolean canUseAction = true;
@@ -81,28 +75,35 @@ public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(name = "enable-locator-bar", comments = """
Enable locator bar for fakeplayers""")
public static boolean enableLocatorBar = false;
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
@DoNotLoad
private BotCommand command = null;
private boolean registered = false;
public static int getSimulationDistance(ServerBot bot) {
return simulationDistance == -1 ? bot.getBukkitEntity().getSimulationDistance() : simulationDistance;
}
public static ServerBot.TickType tickType() {
return FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer
? ServerBot.TickType.NETWORK
: ServerBot.TickType.ENTITY_LIST;
}
public static boolean checkEnabled() {
return enable || FakePlayerCompatConfig.commandPlayer;
}
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enable) {
command = new BotCommand();
command = new BotCommand("bot");
command.register();
registered = true;
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (registered) {
if (command != null) {
command.unregister();
command = null;
}
@@ -11,7 +11,9 @@ public class LanguageConfig implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "lang", comments = """
Please use the key from https://minecraft.wiki/w/Language
Sample of format: en_us zh_cn zh_hk zh_tw""")
Sample of format: en_us zh_cn zh_hk zh_tw
ATTENTION: If you want to edit language for carpet ststem,
please edit it in carpet config file.""")
public static String lang = "en_us";
@ConfigInfo(name = "full_blocking_load", comments = """
@@ -3,34 +3,34 @@ package fun.bm.lophine.utils.concurrent;
import java.util.List;
import java.util.Map;
public abstract class AbstractConcurrentTable<X, Y, Z> {
public abstract void put(X x, Y y, Z z);
public interface AbstractConcurrentTable<X, Y, Z> {
void put(X x, Y y, Z z);
public abstract void remove(X x, Y y, Z z);
void remove(X x, Y y, Z z);
public abstract List<Z> getZ(X x, Y y);
List<Z> getZ(X x, Y y);
public abstract List<Y> getY(X x, Z z);
List<Y> getY(X x, Z z);
public abstract List<X> getX(Y y, Z z);
List<X> getX(Y y, Z z);
public abstract Map<X, Y> getXY(Z z);
Map<X, Y> getXY(Z z);
public abstract Map<Y, Z> getYZ(X x);
Map<Y, Z> getYZ(X x);
public abstract Map<X, Z> getXZ(Y y);
Map<X, Z> getXZ(Y y);
public abstract List<X> getAllX();
List<X> getAllX();
public abstract List<Y> getAllY();
List<Y> getAllY();
public abstract List<Z> getAllZ();
List<Z> getAllZ();
public abstract void clearXY(Z z);
void clearXY(Z z);
public abstract void clearYZ(X x);
void clearYZ(X x);
public abstract void clearXZ(Y y);
void clearXZ(Y y);
public abstract void clearAll();
void clearAll();
}
@@ -7,7 +7,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Predicate;
public class ConcurrentTable<X, Y, Z> extends AbstractConcurrentTable<X, Y, Z> {
public class ConcurrentTable<X, Y, Z> implements AbstractConcurrentTable<X, Y, Z> {
protected final ConcurrentLinkedDeque<TableEntry<X, Y, Z>> data = new ConcurrentLinkedDeque<>();
protected final boolean flagX;
protected final boolean flagY;
@@ -60,88 +60,88 @@ public class ConcurrentTable<X, Y, Z> extends AbstractConcurrentTable<X, Y, Z> {
@Override
public void remove(X x, Y y, Z z) {
data.removeIf(entry -> entry.getX().equals(x) && entry.getY().equals(y) && entry.getZ().equals(z));
data.removeIf(entry -> entry.x().equals(x) && entry.y().equals(y) && entry.z().equals(z));
}
@Override
public List<Z> getZ(X x, Y y) {
return filterAndCollect(
entry -> entry.getX().equals(x) && entry.getY().equals(y),
TableEntry::getZ
entry -> entry.x().equals(x) && entry.y().equals(y),
TableEntry::z
);
}
@Override
public List<Y> getY(X x, Z z) {
return filterAndCollect(
entry -> entry.getX().equals(x) && entry.getZ().equals(z),
TableEntry::getY
entry -> entry.x().equals(x) && entry.z().equals(z),
TableEntry::y
);
}
@Override
public List<X> getX(Y y, Z z) {
return filterAndCollect(
entry -> entry.getY().equals(y) && entry.getZ().equals(z),
TableEntry::getX
entry -> entry.y().equals(y) && entry.z().equals(z),
TableEntry::x
);
}
@Override
public Map<X, Y> getXY(Z z) {
return filterAndMap(
entry -> entry.getZ().equals(z),
TableEntry::getX,
TableEntry::getY
entry -> entry.z().equals(z),
TableEntry::x,
TableEntry::y
);
}
@Override
public Map<Y, Z> getYZ(X x) {
return filterAndMap(
entry -> entry.getX().equals(x),
TableEntry::getY,
TableEntry::getZ
entry -> entry.x().equals(x),
TableEntry::y,
TableEntry::z
);
}
@Override
public Map<X, Z> getXZ(Y y) {
return filterAndMap(
entry -> entry.getY().equals(y),
TableEntry::getX,
TableEntry::getZ
entry -> entry.y().equals(y),
TableEntry::x,
TableEntry::z
);
}
@Override
public List<X> getAllX() {
return collectAll(TableEntry::getX);
return collectAll(TableEntry::x);
}
@Override
public List<Y> getAllY() {
return collectAll(TableEntry::getY);
return collectAll(TableEntry::y);
}
@Override
public List<Z> getAllZ() {
return collectAll(TableEntry::getZ);
return collectAll(TableEntry::z);
}
@Override
public void clearXY(Z z) {
data.removeIf(entry -> entry.getZ().equals(z));
data.removeIf(entry -> entry.z().equals(z));
}
@Override
public void clearYZ(X x) {
data.removeIf(entry -> entry.getX().equals(x));
data.removeIf(entry -> entry.x().equals(x));
}
@Override
public void clearXZ(Y y) {
data.removeIf(entry -> entry.getY().equals(y));
data.removeIf(entry -> entry.y().equals(y));
}
@Override
@@ -76,9 +76,9 @@ public class OptimizedConcurrentTable<X, Y, Z> extends ConcurrentTable<X, Y, Z>
data.removeIf(entry -> {
boolean shouldRemove = predicate.test(entry);
if (shouldRemove) {
removeFromIndex(xyIndex, entry.getX(), entry.getY(), entry.getZ());
removeFromIndex(yzIndex, entry.getY(), entry.getZ(), entry.getX());
removeFromIndex(zxIndex, entry.getZ(), entry.getX(), entry.getY());
removeFromIndex(xyIndex, entry.x(), entry.y(), entry.z());
removeFromIndex(yzIndex, entry.y(), entry.z(), entry.x());
removeFromIndex(zxIndex, entry.z(), entry.x(), entry.y());
}
return shouldRemove;
});
@@ -86,9 +86,9 @@ public class OptimizedConcurrentTable<X, Y, Z> extends ConcurrentTable<X, Y, Z>
public boolean putIfAbsent(X x, Y y, Z z) {
if (data.stream().anyMatch(entry ->
Objects.equals(entry.getX(), x) &&
Objects.equals(entry.getY(), y) &&
Objects.equals(entry.getZ(), z))) {
Objects.equals(entry.x(), x) &&
Objects.equals(entry.y(), y) &&
Objects.equals(entry.z(), z))) {
return false;
}
put(x, y, z);
@@ -1,25 +1,4 @@
package fun.bm.lophine.utils.concurrent;
public class TableEntry<X, Y, Z> {
private final X x;
private final Y y;
private final Z z;
public TableEntry(X x, Y y, Z z) {
this.x = x;
this.y = y;
this.z = z;
}
public X getX() {
return x;
}
public Y getY() {
return y;
}
public Z getZ() {
return z;
}
public record TableEntry<X, Y, Z>(X x, Y y, Z z) {
}
@@ -22,6 +22,7 @@ import com.google.common.collect.Maps;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import fun.bm.lophine.config.modules.function.OldFeatureConfig;
import io.papermc.paper.adventure.PaperAdventure;
@@ -50,10 +51,12 @@ import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.event.entity.EntityRemoveEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.event.bot.*;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import org.slf4j.Logger;
import java.util.*;
@@ -100,7 +103,7 @@ public class BotList {
}
public void saveAllResumeBots() {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
return;
}
for (ServerBot bot : this.bots) {
@@ -190,7 +193,11 @@ public class BotList {
bot.isRealPlayer = true;
bot.loginTime = System.currentTimeMillis();
bot.connection = new ServerBotPacketListenerImpl(this.server, bot);
if (bot.connection.connection.getPlayer() != bot) {
throw new IllegalStateException("Bot connection is not bound to its bot player");
}
bot.connection.markClientLoaded();
bot.getBukkitEntity().setMetadata("NPC", new FixedMetadataValue(MinecraftInternalPlugin.INSTANCE, true));
bot.setServerLevel(world);
BotSpawnLocationEvent event = new BotSpawnLocationEvent(bot.getBukkitEntity(), location);
@@ -347,7 +354,7 @@ public class BotList {
for (String fullName : this.botsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())) {
ServerBot bot = this.getBotByName(fullName);
if (bot != null) {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
}
}
}
@@ -357,9 +364,9 @@ public class BotList {
AtomicInteger check = new AtomicInteger();
AtomicInteger received = new AtomicInteger();
for (ServerBot bot : this.bots) {
bot.resume = FakeplayerConfig.canResident;
bot.resume = FakePlayerCompatConfig.fakePlayerResident;
if (TickThread.isTickThreadFor(bot.level(), bot.getX(), bot.getZ())) {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
} else {
finished = false;
check.getAndIncrement();
@@ -376,7 +383,7 @@ public class BotList {
}
counter.getAndIncrement();
try {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
received.getAndIncrement();
} catch (Exception e) {
this.removeBot(bot, check, received, counter);
@@ -389,7 +396,7 @@ public class BotList {
}
public void loadResumeBotInfo() {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
return;
}
CompoundTag savedBotList = this.getResumeBotList().copy();
@@ -425,7 +432,7 @@ public class BotList {
}
public void loadResume(String worldUuid) {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
return;
}
new HashSet<>(this.botsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())).forEach(this::loadNewResumeBot);
@@ -358,7 +358,7 @@ public class ServerBot extends ServerPlayer {
@Override
public @NotNull InteractionResult interact(@NotNull Player player, @NotNull InteractionHand hand, @NotNull net.minecraft.world.phys.Vec3 location) { // Leaves - Paper 26.1: Entity#interact now takes Vec3
if (FakeplayerConfig.canOpenInventory) {
if (FakePlayerCompatConfig.openFakePlayerInventory) {
if (player instanceof ServerPlayer player1 && player.getMainHandItem().isEmpty()) {
BotInventoryOpenEvent event = new BotInventoryOpenEvent(this.getBukkitEntity(), player1.getBukkitEntity());
getServer().server.getPluginManager().callEvent(event);
@@ -417,23 +417,31 @@ public class ServerBot extends ServerPlayer {
super.readAdditionalSaveData(nbt);
this.setShiftKeyDown(nbt.getBooleanOr("isShiftKeyDown", false));
CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC).orElseThrow();
CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC)
.orElseThrow(() -> new IllegalArgumentException("Missing bot createStatus"));
String rawName = createNbt.getString("rawName")
.orElseGet(() -> createNbt.getString("realName")
.orElseThrow(() -> new IllegalArgumentException("Missing bot rawName")));
String name = createNbt.getString("name")
.orElseThrow(() -> new IllegalArgumentException("Missing bot name"));
String skinName = createNbt.getStringOr("skinName", rawName);
BotCreateState.Builder createBuilder = BotCreateState
.builder(createNbt.getString("rawName")
.orElseGet(() -> createNbt.getString("realName")
.orElseThrow()), null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version
.name(createNbt.getString("name").orElseThrow());
.builder(rawName, null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version
.name(name);
String[] skin = null;
if (createNbt.contains("skin")) {
ListTag skinTag = createNbt.getList("skin").orElseThrow();
ListTag skinTag = createNbt.getList("skin")
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin list"));
skin = new String[skinTag.size()];
for (int i = 0; i < skinTag.size(); i++) {
skin[i] = skinTag.getString(i).orElseThrow();
final int skinIndex = i;
skin[i] = skinTag.getString(i)
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin entry at index " + skinIndex));
}
}
createBuilder.skinName(createNbt.getString("skinName").orElseThrow()).skin(skin);
createBuilder.skinName(skinName).skin(skin);
createBuilder.createReason(BotCreateEvent.CreateReason.INTERNAL).creator(null);
this.createState = createBuilder.build();
@@ -443,11 +451,17 @@ public class ServerBot extends ServerPlayer {
if (FakePlayerCompatConfig.fakePlayerReloadAction && nbt.list("actions", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> actionNbt = nbt.list("actions", CompoundTag.CODEC).orElseThrow();
actionNbt.forEach(actionTag -> {
AbstractBotAction<?> action = Actions.getForName(actionTag.getString("actionName").orElseThrow());
if (action != null) {
AbstractBotAction<?> newAction = action.create();
newAction.load(actionTag);
this.actions.add(newAction);
try {
String actionName = actionTag.getString("actionName")
.orElseThrow(() -> new IllegalArgumentException("Missing actionName"));
AbstractBotAction<?> action = Actions.getForName(actionName);
if (action != null) {
AbstractBotAction<?> newAction = action.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
} catch (RuntimeException exception) {
LophineLogger.LOGGER.warn("Skipped invalid saved action for bot {}", this.getScoreboardName(), exception);
}
});
}
@@ -455,10 +469,16 @@ public class ServerBot extends ServerPlayer {
if (nbt.list("configs", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> configNbt = nbt.list("configs", CompoundTag.CODEC).orElseThrow();
for (CompoundTag configTag : configNbt) {
AbstractBotConfig<?, ?> config = Configs.getConfig(configTag.getString("configName").orElseThrow());
if (config != null) {
config.setBot(this);
config.load(configTag);
try {
String configName = configTag.getString("configName")
.orElseThrow(() -> new IllegalArgumentException("Missing configName"));
AbstractBotConfig<?, ?> config = Configs.getConfig(configName);
if (config != null) {
config.setBot(this);
config.load(configTag);
}
} catch (RuntimeException exception) {
LophineLogger.LOGGER.warn("Skipped invalid saved config for bot {}", this.getScoreboardName(), exception);
}
}
}
@@ -31,7 +31,12 @@ import org.jetbrains.annotations.Nullable;
public class ServerBotPacketListenerImpl extends ServerGamePacketListenerImpl {
public ServerBotPacketListenerImpl(MinecraftServer server, ServerBot bot) {
super(server, BotConnection.INSTANCE, bot, CommonListenerCookie.createInitial(bot.gameProfile, false));
this(server, bot, new BotConnection());
}
private ServerBotPacketListenerImpl(MinecraftServer server, ServerBot bot, BotConnection connection) {
super(server, connection, bot, CommonListenerCookie.createInitial(bot.gameProfile, false));
connection.bind(this);
}
@Override
@@ -53,12 +58,14 @@ public class ServerBotPacketListenerImpl extends ServerGamePacketListenerImpl {
public static class BotConnection extends Connection {
private static final BotConnection INSTANCE = new BotConnection();
public BotConnection() {
super(PacketFlow.SERVERBOUND);
}
private void bind(ServerBotPacketListenerImpl listener) {
this.packetListener = listener;
}
@Override
public void tick() {
}
@@ -31,7 +31,7 @@ public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType, TickTy
public TickTypeConfig() {
super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class), TickTypeConfig::new);
this.value = FakeplayerConfig.tickType;
this.value = FakeplayerConfig.tickType();
}
@Override
@@ -59,7 +59,7 @@ public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType, TickTy
@Override
public void load(@NotNull CompoundTag nbt) {
String raw = nbt.getStringOr(getName(), FakeplayerConfig.tickType.name());
String raw = nbt.getStringOr(getName(), FakeplayerConfig.tickType().name());
this.setValue(switch (raw.toLowerCase(Locale.ROOT)) {
case "network" -> ServerBot.TickType.NETWORK;
case "entity_list" -> ServerBot.TickType.ENTITY_LIST;
@@ -29,8 +29,8 @@ import static org.leavesmc.leaves.command.CommandUtils.registerPermissions;
public class BotCommand extends RootNode {
private static final String PERM_BASE = "bukkit.command.bot";
public BotCommand() {
super("bot", PERM_BASE);
public BotCommand(String key) {
super(key, PERM_BASE);
this.children(
ListCommand::new,
ConfigCommand::new,
@@ -45,6 +45,7 @@ import java.util.jar.JarFile;
public class LeavesProtocolManager {
private static final Logger LOGGER = LogUtils.getClassLogger();
private static final LeavesCustomPayload INVALID_PAYLOAD = new InvalidPayload();
private static final Map<Class<? extends LeavesCustomPayload>, PayloadReceiverInvokerHolder> PAYLOAD_RECEIVERS = new HashMap<>();
private static final Map<Class<? extends LeavesCustomPayload>, Identifier> IDS = new HashMap<>();
@@ -217,8 +218,8 @@ public class LeavesProtocolManager {
try {
return codec.decode(ProtocolUtils.decorate(buf));
} catch (Exception e) {
LOGGER.error("Failed to decode payload {}", location, e);
throw e;
LOGGER.warn("Rejected malformed Leaves payload {}", location, e);
return INVALID_PAYLOAD;
}
}
@@ -238,9 +239,16 @@ public class LeavesProtocolManager {
}
public static void handlePayload(IdentifierSelector selector, LeavesCustomPayload payload) {
if (payload == INVALID_PAYLOAD) {
return;
}
PayloadReceiverInvokerHolder holder;
if ((holder = PAYLOAD_RECEIVERS.get(payload.getClass())) != null) {
holder.invoke(selector, payload);
try {
holder.invoke(selector, payload);
} catch (RuntimeException exception) {
LOGGER.warn("Rejected malformed Leaves payload {} from {}", payload.getClass().getName(), describeSelector(selector), exception);
}
}
}
@@ -248,22 +256,44 @@ public class LeavesProtocolManager {
RegistryFriendlyByteBuf buf1 = ProtocolUtils.decorate(buf);
BytebufReceiverInvokerHolder holder;
if ((holder = STRICT_BYTEBUF_RECEIVERS.get(location.toString())) != null) {
holder.invoke(selector, buf1);
safeInvokeBytebuf(holder, selector, location, buf1);
return true;
}
if ((holder = NAMESPACED_BYTEBUF_RECEIVERS.get(location.getNamespace())) != null) {
if (holder.invoke(selector, buf1)) {
if (safeInvokeBytebuf(holder, selector, location, buf1)) {
return true;
}
}
for (var holder1 : GENERIC_BYTEBUF_RECEIVERS) {
if (holder1.invoke(selector, buf1)) {
if (safeInvokeBytebuf(holder1, selector, location, buf1)) {
return true;
}
}
return false;
}
private static boolean safeInvokeBytebuf(BytebufReceiverInvokerHolder holder, IdentifierSelector selector, Identifier location, RegistryFriendlyByteBuf buf) {
try {
return holder.invoke(selector, buf);
} catch (RuntimeException exception) {
LOGGER.warn("Rejected malformed bytebuf payload {} from {}", location, describeSelector(selector), exception);
return true;
}
}
private static String describeSelector(IdentifierSelector selector) {
if (selector.player() != null) {
return selector.player().getScoreboardName();
}
if (selector.context() != null) {
return selector.context().profile().name();
}
return "unknown";
}
private record InvalidPayload() implements LeavesCustomPayload {
}
public static void handleTick() {
long currentTime = System.currentTimeMillis() / MinecraftServer.getServer().tickRateManager().nanosecondsPerTick();
if (currentTime == lastAcceptTime) return;
@@ -414,4 +444,4 @@ public class LeavesProtocolManager {
}
}
}
}
}
@@ -400,15 +400,25 @@ public class REIServerProtocol implements LeavesProtocol {
private static List<List<ItemStack>> readInputs(RegistryAccess registryAccess, ListTag tag) {
List<List<ItemStack>> items = new ArrayList<>();
for (Tag t : tag) {
CompoundTag compoundTag = (CompoundTag) t;
compoundTag.getInt("Index").orElseThrow();
if (!(t instanceof CompoundTag compoundTag)) {
throw new IllegalStateException("Invalid REI input entry");
}
if (compoundTag.getInt("Index").isEmpty()) {
throw new IllegalStateException("Missing REI input index");
}
ListTag ingredientList = compoundTag.getListOrEmpty("Ingredient");
List<ItemStack> slotItems = new ArrayList<>();
for (Tag ingredient : ingredientList) {
CompoundTag ingredientTag = (CompoundTag) ingredient;
if (!(ingredient instanceof CompoundTag ingredientTag)) {
throw new IllegalStateException("Invalid REI ingredient entry");
}
Tag value = ingredientTag.get("value");
if (value == null) {
throw new IllegalStateException("Missing REI ingredient value");
}
ItemStack stack = ItemStack.OPTIONAL_CODEC.parse(
registryAccess.createSerializationContext(NbtOps.INSTANCE),
ingredientTag.get("value")
value
).getOrThrow();
slotItems.add(stack);
}
@@ -420,16 +430,28 @@ public class REIServerProtocol implements LeavesProtocol {
private static List<SlotAccessor> readSlots(AbstractContainerMenu menu, ServerPlayer player, ListTag tag) {
List<SlotAccessor> slots = new ArrayList<>();
for (Tag t : tag) {
CompoundTag compoundTag = (CompoundTag) t;
String id = compoundTag.getString("id").orElseThrow();
if (!(t instanceof CompoundTag compoundTag)) {
throw new IllegalStateException("Invalid REI slot entry");
}
String id = compoundTag.getString("id").orElseThrow(() -> new IllegalStateException("Missing REI slot id"));
if (!id.startsWith(PROTOCOL_ID + ":")) {
throw new IllegalStateException("Invalid slot id: " + id + ", expected to start with '" + PROTOCOL_ID + ":'");
}
id = id.substring((PROTOCOL_ID + ":").length());
int slot = compoundTag.getInt("Slot").orElseThrow();
int slot = compoundTag.getInt("Slot").orElseThrow(() -> new IllegalStateException("Missing REI slot index"));
SlotAccessor accessor = switch (id) {
case "vanilla" -> new VanillaSlotAccessor(menu.slots.get(slot));
case "player" -> new PlayerInventorySlotAccessor(player, slot);
case "vanilla" -> {
if (slot < 0 || slot >= menu.slots.size()) {
throw new IllegalStateException("Invalid vanilla slot index: " + slot);
}
yield new VanillaSlotAccessor(menu.slots.get(slot));
}
case "player" -> {
if (slot < 0 || slot >= player.getInventory().getContainerSize()) {
throw new IllegalStateException("Invalid player slot index: " + slot);
}
yield new PlayerInventorySlotAccessor(player, slot);
}
default -> throw new IllegalStateException("Unknown container id: " + id);
};
slots.add(accessor);
@@ -51,17 +51,21 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
public static final int MINECRAFT_DATA_VERSION = SharedConstants.getProtocolVersion();
public static final int SCHEMATIC_VERSION = 7;
private static final long MAX_REGION_VOLUME = 16_777_216L;
@NotNull
@Contract("_ -> new")
public static LitematicaSchematic readFromNBT(@NotNull CompoundTag nbt) {
if (nbt.contains("Version")) {
final int version = nbt.getIntOr("Version", -1);
final int minecraftDataVersion = nbt.contains("MinecraftDataVersion") ? nbt.getInt("MinecraftDataVersion").orElseThrow() : SharedConstants.getProtocolVersion();
final int minecraftDataVersion = nbt.getIntOr("MinecraftDataVersion", SharedConstants.getProtocolVersion());
if (version >= 1 && version <= SCHEMATIC_VERSION) {
SchematicMetadata metadata = SchematicMetadata.readFromNBT(nbt.getCompoundOrEmpty("Metadata"), version, minecraftDataVersion, FileType.LITEMATICA_SCHEMATIC);
Map<String, SubRegion> subRegions = readSubRegionsFromNBT(nbt.getCompoundOrEmpty("Regions"), version, minecraftDataVersion);
if (subRegions.isEmpty()) {
throw new IllegalArgumentException("Schematic has no regions");
}
return new LitematicaSchematic(subRegions, metadata);
} else {
throw new RuntimeException("Unsupported or future schematic version");
@@ -116,6 +120,7 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
if (position == null || size == null) {
throw new IllegalArgumentException("Invalid region");
}
validateRegionSize(size);
Map<BlockPos, CompoundTag> tileEntities;
List<EntityInfo> entities;
@@ -141,6 +146,9 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
Tag blockState = regionTag.get("BlockStates");
if (blockState != null && blockState.getId() == Tag.TAG_LONG_ARRAY) {
ListTag palette = regionTag.getListOrEmpty("BlockStatePalette");
if (palette.isEmpty()) {
throw new IllegalArgumentException("Missing block state palette");
}
long[] blockStateArr = ((LongArrayTag) blockState).getAsLongArray();
BlockPos posEndRel = PositionUtils.getRelativeEndPositionFromAreaSize(size).offset(position);
BlockPos posMin = PositionUtils.getMinCorner(position, posEndRel);
@@ -155,6 +163,19 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
return new SubRegion(blockContainers, tileEntities, pendingBlockTicks, pendingFluidTicks, entities, position, size);
}
private static void validateRegionSize(BlockPos size) {
long x = Math.abs((long) size.getX());
long y = Math.abs((long) size.getY());
long z = Math.abs((long) size.getZ());
if (x == 0 || y == 0 || z == 0) {
throw new IllegalArgumentException("Region has zero size");
}
long volume = Math.multiplyExact(Math.multiplyExact(x, y), z);
if (volume > MAX_REGION_VOLUME) {
throw new IllegalArgumentException("Region volume too large: " + volume);
}
}
private static List<EntityInfo> readEntitiesFromNBT(ListTag tagList) {
List<EntityInfo> entityList = new ArrayList<>();
final int size = tagList.size();
@@ -278,4 +299,4 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
this.nbt = nbt;
}
}
}
}
@@ -264,12 +264,17 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
}
if (tags.getStringOr("Task", "").equals("LitematicaPaste")) {
ServuxProtocol.LOGGER.debug("litematic_data: Servux Paste request from player {}", player.getName().getString());
ServerLevel serverLevel = player.level();
long timeStart = System.currentTimeMillis();
SchematicPlacement placement = SchematicPlacement.createFromNbt(tags);
ReplaceBehavior replaceMode = ReplaceBehavior.fromStringStatic(tags.getStringOr("ReplaceMode", ReplaceBehavior.NONE.name()));
placement.pasteTo(serverLevel, replaceMode, player, timeStart);
try {
ServuxProtocol.LOGGER.debug("litematic_data: Servux Paste request from player {}", player.getName().getString());
ServerLevel serverLevel = player.level();
long timeStart = System.currentTimeMillis();
SchematicPlacement placement = SchematicPlacement.createFromNbt(tags);
ReplaceBehavior replaceMode = ReplaceBehavior.fromStringStatic(tags.getStringOr("ReplaceMode", ReplaceBehavior.NONE.name()));
placement.pasteTo(serverLevel, replaceMode, player, timeStart);
} catch (RuntimeException exception) {
player.getBukkitEntity().sendActionBar(Component.text("Invalid Litematica paste data", NamedTextColor.RED));
ServuxProtocol.LOGGER.warn("Rejected invalid Litematica paste request from {}", player.getScoreboardName(), exception);
}
}
}
@@ -438,4 +443,4 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
return !this.hasBuffer() && !this.hasNbt();
}
}
}
}
@@ -20,7 +20,6 @@ package org.leavesmc.leaves.protocol.servux.litematics.container;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nullable;
import java.util.Objects;
public class LitematicaBitArray {
/**
@@ -47,11 +46,19 @@ public class LitematicaBitArray {
public LitematicaBitArray(int bitsPerEntryIn, long arraySizeIn, @Nullable long[] longArrayIn) {
Validate.inclusiveBetween(1L, 32L, bitsPerEntryIn);
Validate.isTrue(arraySizeIn >= 0L, "arraySize must not be negative");
this.arraySize = arraySizeIn;
this.bitsPerEntry = bitsPerEntryIn;
this.maxEntryValue = (1L << bitsPerEntryIn) - 1L;
this.longArray = Objects.requireNonNullElseGet(longArrayIn, () -> new long[(int) (roundUp(arraySizeIn * bitsPerEntryIn, 64L) / 64L)]);
long backingLength = roundUp(Math.multiplyExact(arraySizeIn, bitsPerEntryIn), 64L) / 64L;
Validate.isTrue(backingLength <= Integer.MAX_VALUE, "BitArray backing storage is too large");
if (longArrayIn != null) {
Validate.isTrue(longArrayIn.length >= backingLength, "BitArray backing storage is too small");
this.longArray = longArrayIn;
} else {
this.longArray = new long[(int) backingLength];
}
}
public static long roundUp(long value, long interval) {
@@ -71,6 +78,7 @@ public class LitematicaBitArray {
}
public void setAt(long index, int value) {
this.checkIndex(index);
long startOffset = index * (long) this.bitsPerEntry;
int startArrIndex = (int) (startOffset >> 6); // startOffset / 64
int endArrIndex = (int) (((index + 1L) * (long) this.bitsPerEntry - 1L) >> 6);
@@ -85,6 +93,7 @@ public class LitematicaBitArray {
}
public int getAt(long index) {
this.checkIndex(index);
long startOffset = index * (long) this.bitsPerEntry;
int startArrIndex = (int) (startOffset >> 6); // startOffset / 64
int endArrIndex = (int) (((index + 1L) * (long) this.bitsPerEntry - 1L) >> 6);
@@ -101,4 +110,10 @@ public class LitematicaBitArray {
public long size() {
return this.arraySize;
}
}
private void checkIndex(long index) {
if (index < 0L || index >= this.arraySize) {
throw new IndexOutOfBoundsException("BitArray index " + index + " out of bounds for length " + this.arraySize);
}
}
}
@@ -49,7 +49,9 @@ public interface LitematicaBlockStatePalette {
final int size = tagList.size();
for (int i = 0; i < size; ++i) {
CompoundTag tag = tagList.getCompound(i).orElseThrow();
final int paletteIndex = i;
CompoundTag tag = tagList.getCompound(i)
.orElseThrow(() -> new IllegalArgumentException("Invalid block state palette entry at index " + paletteIndex));
BlockState state = NbtUtils.readBlockState(lookup, tag);
if (i > 0 || state != LitematicaBlockStateContainer.AIR_BLOCK_STATE) {
@@ -59,4 +61,4 @@ public interface LitematicaBlockStatePalette {
}
ListTag writeToNBT();
}
}
@@ -42,7 +42,10 @@ import org.leavesmc.leaves.protocol.servux.litematics.selection.Box;
import org.leavesmc.leaves.protocol.servux.litematics.utils.*;
import javax.annotation.Nullable;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
@@ -62,20 +65,31 @@ public class SchematicPlacement {
}
public static SchematicPlacement createFromNbt(CompoundTag tags) {
if (!tags.contains("Schematics")) {
throw new IllegalArgumentException("Missing Schematics tag");
}
BlockPos origin = NbtUtils.readBlockPosFromArrayTag(tags, "Origin");
if (origin == null) {
throw new IllegalArgumentException("Missing or invalid Origin tag");
}
SchematicPlacement placement = new SchematicPlacement(
LitematicaSchematic.readFromNBT(tags.getCompoundOrEmpty("Schematics")),
NbtUtils.readBlockPosFromArrayTag(tags, "Origin"),
origin,
tags.getStringOr("Name", "")
);
placement.mirror = Mirror.values()[tags.getIntOr("Mirror", 0)];
placement.rotation = Rotation.values()[tags.getIntOr("Rotation", 0)];
placement.mirror = enumByOrdinal(Mirror.values(), tags.getIntOr("Mirror", 0), "Mirror");
placement.rotation = enumByOrdinal(Rotation.values(), tags.getIntOr("Rotation", 0), "Rotation");
for (String name : tags.getCompoundOrEmpty("SubRegions").keySet()) {
CompoundTag compound = tags.getCompoundOrEmpty("SubRegions").getCompoundOrEmpty(name);
BlockPos pos = NbtUtils.readBlockPosFromArrayTag(compound, "Pos");
if (pos == null) {
throw new IllegalArgumentException("Missing or invalid Pos tag for sub-region " + name);
}
var sub = new SubRegionPlacement(
compound.getStringOr("Name", "?"),
NbtUtils.readBlockPosFromArrayTag(compound, "Pos"),
Rotation.values()[compound.getIntOr("Rotation", 0)],
Mirror.values()[compound.getIntOr("Mirror", 0)],
pos,
enumByOrdinal(Rotation.values(), compound.getIntOr("Rotation", 0), "SubRegions." + name + ".Rotation"),
enumByOrdinal(Mirror.values(), compound.getIntOr("Mirror", 0), "SubRegions." + name + ".Mirror"),
compound.getBooleanOr("Enabled", true),
compound.getBooleanOr("IgnoreEntities", false)
);
@@ -84,6 +98,13 @@ public class SchematicPlacement {
return placement;
}
private static <T> T enumByOrdinal(T[] values, int ordinal, String tagName) {
if (ordinal < 0 || ordinal >= values.length) {
throw new IllegalArgumentException("Invalid " + tagName + " ordinal: " + ordinal);
}
return values[ordinal];
}
public static IntBoundingBox getBoundsWithinChunkForBox(Box box, int chunkX, int chunkZ) {
final int chunkXMin = chunkX << 4;
final int chunkZMin = chunkZ << 4;
@@ -302,7 +323,13 @@ public class SchematicPlacement {
AtomicInteger count_full = new AtomicInteger();
AtomicInteger count = new AtomicInteger();
streamChunkPos(Objects.requireNonNull(enclosingBox.toVanilla())).forEach(chunkPos -> {
BlockBox vanillaBox = enclosingBox.toVanilla();
if (vanillaBox == null) {
ServuxProtocol.LOGGER.error("receiver a null vanilla enclosing box");
return;
}
streamChunkPos(vanillaBox).forEach(chunkPos -> {
RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
serverWorld,
chunkPos.x(),
@@ -51,6 +51,7 @@ public class CommunicationManager implements LeavesProtocol {
protected static final Map<UUID, Exchange> modifyState = new ConcurrentHashMap<>();
protected static final Rotation[] rotOrdinals = Rotation.values();
protected static final Mirror[] mirOrdinals = Mirror.values();
private static final int MAX_SUB_REGION_MODIFICATIONS = 4096;
private static final Map<UUID, List<ServerPlacement>> downloadingFile = new ConcurrentHashMap<>();
private static final Map<ExchangeTarget, ServerPlayer> playerMap = new ConcurrentHashMap<>();
@@ -87,7 +88,11 @@ public class CommunicationManager implements LeavesProtocol {
@ProtocolHandler.PayloadReceiver(payload = SyncmaticaPayload.class)
public static void onPacketGet(ServerPlayer player, SyncmaticaPayload payload) {
onPacket(player.connection.exchangeTarget, payload.packetType(), payload.data());
try {
onPacket(player.connection.exchangeTarget, payload.packetType(), payload.data());
} catch (IllegalArgumentException | IndexOutOfBoundsException exception) {
LOGGER.warn("Rejected malformed Syncmatica packet {} from {}", payload.packetType(), player.getScoreboardName(), exception);
}
}
public static void onPacket(final @NotNull ExchangeTarget source, final Identifier id, final FriendlyByteBuf packetBuf) {
@@ -326,20 +331,30 @@ public class CommunicationManager implements LeavesProtocol {
public static void receivePositionData(final @NotNull ServerPlacement placement, final @NotNull FriendlyByteBuf buf, final @NotNull ExchangeTarget exchangeTarget) {
final BlockPos pos = buf.readBlockPos();
final String dimensionId = buf.readUtf(32767);
final Rotation rot = rotOrdinals[buf.readInt()];
final Mirror mir = mirOrdinals[buf.readInt()];
final Rotation rot = readOrdinal(rotOrdinals, buf.readInt(), "rotation");
final Mirror mir = readOrdinal(mirOrdinals, buf.readInt(), "mirror");
placement.move(dimensionId, pos, rot, mir);
if (exchangeTarget.getFeatureSet().hasFeature(Feature.CORE_EX)) {
final SubRegionData subRegionData = placement.getSubRegionData();
subRegionData.reset();
final int limit = buf.readInt();
if (limit < 0 || limit > MAX_SUB_REGION_MODIFICATIONS) {
throw new IllegalArgumentException("Invalid sub-region modification count: " + limit);
}
for (int i = 0; i < limit; i++) {
subRegionData.modify(buf.readUtf(32767), buf.readBlockPos(), rotOrdinals[buf.readInt()], mirOrdinals[buf.readInt()]);
subRegionData.modify(buf.readUtf(32767), buf.readBlockPos(), readOrdinal(rotOrdinals, buf.readInt(), "sub-region rotation"), readOrdinal(mirOrdinals, buf.readInt(), "sub-region mirror"));
}
}
}
private static <T> T readOrdinal(T[] values, int ordinal, String name) {
if (ordinal < 0 || ordinal >= values.length) {
throw new IllegalArgumentException("Invalid " + name + " ordinal: " + ordinal);
}
return values[ordinal];
}
public static void download(final ServerPlacement syncmatic, final ExchangeTarget source) throws NoSuchAlgorithmException, IOException {
if (!SyncmaticaProtocol.getFileStorage().getLocalState(syncmatic).isReadyForDownload()) {
throw new IllegalArgumentException(syncmatic.toString() + " is not ready for download local state is: " + SyncmaticaProtocol.getFileStorage().getLocalState(syncmatic).toString());
@@ -17,7 +17,7 @@
package org.leavesmc.leaves.util;
import fun.bm.lophine.config.modules.function.WoolHopperCounterConfig;
import fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig;
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2LongMap;
import net.kyori.adventure.text.Component;
@@ -351,6 +351,6 @@ public class HopperCounter {
}
public static boolean isEnabled() {
return WoolHopperCounterConfig.enabled && enabled;
return WoolHopperCounterConfig.hopperCounters && enabled;
}
}