Compare commits

..

3 Commits

Author SHA1 Message Date
Bacteriawa 481d5bc001 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 02:04:29 +08:00
Bacteriawa 13474bf193 Merge branch 'dev/26.1.2' of https://github.com/LuminolMC/Lophine into dev/26.1.2 2026-06-03 02:02:52 +08:00
Bacteriawa 61990fd9e9 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 02:01:56 +08:00
100 changed files with 901 additions and 1543 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
BUILD_NUMBER: ${{ github.run_number }}
steps:
- name: Checkout Git Repository
uses: actions/checkout@v7
uses: actions/checkout@v6
- name: Set Up JDK
uses: actions/setup-java@v5
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
+1 -1
View File
@@ -45,7 +45,7 @@ git clone https://github.com/LuminolMC/Lophine.git
cd Lophine
# 应用补丁并构建 Paperclip JAR
./gradlew applyAllPatches && ./gradlew createPaperclipJar
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
```
构建完成后,您可以在 `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 createPaperclipJar
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
```
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=STABLE
clipVersion=3.0.18
weightVersion=2.0.15
channel=BETA
clipVersion=3.0.17
weightVersion=2.0.12
# true for release, false for skip release, pre for pre-release
release=true
release=pre
# true for push to repo, false for skip push repo, auto for detect by release value
pushRepo=auto
luminolRef=2a3c21971bf030511823915c8b8d537f6d5963eb
luminolRef=397a754b718e76edbe1a9d6d583054f885db5fde
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.9.0") // Night config
implementation("com.electronwill.night-config:toml:3.8.3") // 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 a2f5a99ee45a0810fd338ccf6f71df3a077ca62b..05e1aa84586284ac0389e7023f975bfb08438535 100644
index 490316c7d5cbb77e988039cfa7a7cc0aa3849730..f5fb4e210c07f32e52eb8c1ba166d1571a6778c7 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() {
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
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
preLoad();
}
@@ -5,10 +5,10 @@ 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 389a31b14912a2dfc8e8b20c104505d211d7f8ad..04b9e3a432181c9698e1a4c147b420c230b66a36 100644
index 0a20c6f03625391201e5ced167707e54ed27daa1..2872b22e44cba48442c526f0a53e1fc6c5ce760f 100644
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
@@ -55,6 +55,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
@@ -46,6 +46,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
return;
}
@@ -21,21 +21,23 @@ index 389a31b14912a2dfc8e8b20c104505d211d7f8ad..04b9e3a432181c9698e1a4c147b420c2
this.waypoints.add(waypoint);
for (ServerPlayer toCreateFor : this.trackingPlayers) {
@@ -111,6 +117,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
@@ -101,7 +107,13 @@ 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 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab5822601939 100644
index 8f0548908a9e43ce29c4476f2707f6898e540aec..8b7c66785a06eb4782de0b0a9b542221d6258220 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 {
@@ -51,6 +53,6 @@ index 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab58
- ));
- }
+ availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
if (Boolean.getBoolean("leavesclip.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 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c 100644
index 8b7c66785a06eb4782de0b0a9b542221d6258220..1f3fe7f786bb8f7c59e3a0235dcc572f3171ee6b 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 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955
private ServerFeatureManager() {
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
if (Boolean.getBoolean("leavesclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -5,22 +5,20 @@ 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 05e1aa84586284ac0389e7023f975bfb08438535..5a8c94337e42584ddaf25ef289327777e7ac675e 100644
index f5fb4e210c07f32e52eb8c1ba166d1571a6778c7..e990c147e1b632ef5a33e4f3c37b5cd608040ac7 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -25,6 +25,15 @@ public class ConfigManager {
@@ -25,6 +25,13 @@ public class ConfigManager {
public static void initConfigs() {
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
+ // Lophine start - add carpet config
+ registerConfig("lophine_carpet", ConfigsInstance.of(
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(
+ new java.io.File("lophine_config"),
+ "lophine_carpet",
+ "lophine_carpet_config.toml",
+ "lophinecarpetconfig",
+ "fun.bm.lophine.carpet.config.modules"
+ ));
+ // Lophine end - add carpet config
+ )); // add lophine carpet config
preLoad();
}
@@ -1,18 +0,0 @@
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);
}
@@ -1,38 +0,0 @@
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;
-}
@@ -1,25 +0,0 @@
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 5a8c94337e42584ddaf25ef289327777e7ac675e..b652525f243c23e09c4e13f67617e99a3ce0db04 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -64,6 +64,12 @@ 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;
+
+ // Lophine start - temporarily transform configs
+ reApplyStagedConfigs();
+ saveConfigs();
+ configfiles.values().forEach((config) -> config.reload(true, false));
+ // Lophine end - temporarily transform configs
}
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 143ad4e342b184aa02b6fbbe81508e244eebc7a2..89be42b8519522398920eb424c894fd2ab8c9666 100644
index 5b46b224bb0fea3a7e0f721ce9770657ffe0c71d..44d594da98615a8bbfb2560e0a63d2e7aab3cc7e 100644
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -155,6 +155,8 @@ public class Main {
@@ -154,6 +154,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 28384f9ebfcdbfbd07fc7fe3c929786eb9e2ccd3..d1cc2f956213add0e04d51db7b9da7076b521d8b 100644
index 35c1b7f40563823401ca204ec41ef57220b5ad55..f993a4de22558e7b9598aa7500cd3cc1225e4c5b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2472,6 +2472,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -26,7 +26,7 @@ index 28384f9ebfcdbfbd07fc7fe3c929786eb9e2ccd3..d1cc2f956213add0e04d51db7b9da707
final Collection<String> packsToEnable, final io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause
) {
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..991e0362e96488b64d994f1bdfb8ed5d66f98666 100644
index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..04fa1c5bb1c0b025a56941aae7d2151d1087e257 100644
--- a/net/minecraft/server/commands/DataPackCommand.java
+++ b/net/minecraft/server/commands/DataPackCommand.java
@@ -98,7 +98,7 @@ public class DataPackCommand {
@@ -34,7 +34,7 @@ index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..991e0362e96488b64d994f1bdfb8ed5d
Commands.literal("datapack")
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
- /*.then( // Luminol - Add back read-only datapack command
+ .then( // Lophine - Fix datapack command save function
+ .then(
Commands.literal("enable")
.then(
Commands.argument("name", StringArgumentType.string())
@@ -57,7 +57,7 @@ index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..991e0362e96488b64d994f1bdfb8ed5d
private static int listPacks(final CommandSourceStack source) {
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
+ return listEnabledPacks(source) + listAvailablePacks(source); // Lophine - Fix datapack command save function
+ return listEnabledPacks(source) + listAvailablePacks(source);
}
private static int listAvailablePacks(final CommandSourceStack source) {
@@ -23,7 +23,7 @@ index 63b81f30b8d813a7986ae72842fdc2d3097fa103..527c495bb4f6007aee760b99cc0e9aa5
// Paper start - whitelist verify event / login event
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 1413286ddc63c5978e745eb26f6012230e4b1cd6..234124cc64e5175c20f9e9f0f482c9c677bca563 100644
index c157aa170d5879206810f4852a96120396b69db7..b9cc33198efceb75dfef333c018b1296944451cb 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -174,6 +174,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -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 e12927623e8de82a6105b0cb0e6b58a6c45cff7e..0b5f2060062a354bd6cafa8f53a5734dc83d062d 100644
index aa9e99358e5f3a5d07d9902708bcfa6255d26b97..47beff71ed33e7fbd6fe6cd47aa955233af41f04 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 11cacb26ce260373476dad764014ba1852477831..981f63b75584dbcb4bb0d5672e8c8bb140c52f9d 100644
index 3416445888860746c15a978f401c87245609b64a..fc6402dd0a47f5b2792aa8a21703bfee18dd2388 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -364,6 +364,8 @@ public final class RegionizedServer {
@@ -359,6 +359,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 89f61f5715942d2b521e04b9fdc8b1b379c0c957..2c2487e1c1c65438119a13bd705a9e44697955ed 100644
index bcb1a5ec17269529ef0f9556043a7183df846eab..4503e62a72e67d35db5b091c91e903058157bdbd 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -299,7 +299,11 @@ public class Commands {
@@ -295,7 +295,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 89f61f5715942d2b521e04b9fdc8b1b379c0c957..2c2487e1c1c65438119a13bd705a9e44
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d1cc2f956213add0e04d51db7b9da7076b521d8b..82013a8f7cf07b6f0645ca6b51ee75fcb0a56298 100644
index f993a4de22558e7b9598aa7500cd3cc1225e4c5b..82315368d5580563fc77548f22a65d04ec73b622 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 cross region damage trace
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index fecab5bfbc35fbecef8c559369de70c198bfe1e7..338e0c7c09120c6e9617893dd074cbd5da40a093 100644
index 6cedc129f31289eaf4e3580219fc1988c0f3c5a1..5f1fad59a26e3fe29f9000a92be5d6c4422dcd01 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1464,6 +1464,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -48,7 +48,7 @@ index fecab5bfbc35fbecef8c559369de70c198bfe1e7..338e0c7c09120c6e9617893dd074cbd5
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index cd2fb9e2110d0dba1358daa283af767db3f4e80a..cc7b2ea7fda1326e3f9ed46373190a05f60c4d34 100644
index 17483ffff6cb2a9e86db7079e7c3a9a800654c62..29919b8f3c05c8ffaf66f86e441778eeefb293b1 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1961,6 +1961,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -5,19 +5,17 @@ Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 2c2487e1c1c65438119a13bd705a9e44697955ed..4e0428948d618b0a072679762dc3cb39d6e12c2f 100644
index 4503e62a72e67d35db5b091c91e903058157bdbd..86866a9fa92d2e1ac0026e5764f459cc73e0b266 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -217,7 +217,11 @@ public class Commands {
@@ -217,7 +217,9 @@ public class Commands {
FillCommand.register(this.dispatcher, context);
FillBiomeCommand.register(this.dispatcher, context);
ForceLoadCommand.register(this.dispatcher);
- //FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ // Lophine start - Add config to enable function command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.function) {
+ FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ }
+ // Lophine end - Add config to enable function command
GameModeCommand.register(this.dispatcher);
GameRuleCommand.register(this.dispatcher, context);
GiveCommand.register(this.dispatcher, context);
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 4e0428948d618b0a072679762dc3cb39d6e12c2f..87ffca5ff0c2775cb85a6058c9be66e00c94f01f 100644
index 86866a9fa92d2e1ac0026e5764f459cc73e0b266..f54f6047f326189329e11338b17105f5555dde12 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -246,7 +246,11 @@ public class Commands {
@@ -244,7 +244,11 @@ public class Commands {
RotateCommand.register(this.dispatcher);
SayCommand.register(this.dispatcher);
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
@@ -17,7 +17,7 @@ index 4e0428948d618b0a072679762dc3cb39d6e12c2f..87ffca5ff0c2775cb85a6058c9be66e0
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.scoreboard) {
+ ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
+ }
+ // Lophine end - Add a config to enable scoreboard command
+ // Lophine start - Add a config to enable scoreboard command
SeedCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
VersionCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
SetBlockCommand.register(this.dispatcher, context);
@@ -1,23 +0,0 @@
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 87ffca5ff0c2775cb85a6058c9be66e00c94f01f..74ef76058e5a410d12f88aa09450e7d90f63b5e6 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -274,7 +274,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 552fd994ee30deb6e9f4228b17a2883cf26b164c..f090b8d77bd2731debfc61c263bd77550f52212b 100644
index 0e543348e48fdf2131dfa1460e37db238d02988c..b69698f47ccb0f1ac3eeea05a02ab9d798319b44 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -167,7 +167,7 @@ public abstract class Entity
@@ -30,11 +30,10 @@ index 552fd994ee30deb6e9f4228b17a2883cf26b164c..f090b8d77bd2731debfc61c263bd7755
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
static boolean isLevelAtLeast(ValueInput input, int level) {
@@ -6432,4 +6432,48 @@ public abstract class Entity
@@ -6412,4 +6412,46 @@ public abstract class Entity
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
+ // Lophine start - Add config to enable raytracing tracker
+
+ private long lasttime = 0;
+ private boolean culled = false;
@@ -77,26 +76,23 @@ index 552fd994ee30deb6e9f4228b17a2883cf26b164c..f090b8d77bd2731debfc61c263bd7755
+ return this.outOfCamera;
+ }
+
+ // Lophine end - Add config to enable raytracing tracker
}
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index cb0a52dc3795e1cf54069bcbe82abf7877a658b8..0d743a01ae70baa789cd0e0bb9abd4c4f8310b99 100644
index cb0a52dc3795e1cf54069bcbe82abf7877a658b8..1440946665f41ebf534d701515f982bbbf4c9686 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1252,6 +1252,11 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
@@ -1252,6 +1252,9 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
public final int passengerTickTimerId;
public final int passengerInactiveTickTimerId;
// Folia end - profiler
+ // Lophine start - Add config to enable raytracing tracker
+ // Luminol - Raytracing entity tracker
+ public boolean skipRaytracningCheck = false;
+ // Luminol end
+ // Lophine end - Add config to enable raytracing tracker
public EntityType(
final EntityType.EntityFactory<T> factory,
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 234124cc64e5175c20f9e9f0f482c9c677bca563..b45481f781f3556001af89704b718d6291ba1f66 100644
index b9cc33198efceb75dfef333c018b1296944451cb..f6f6d21f3393a3ab79a84212b0d66d83d0e817f1 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -185,6 +185,25 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -1,123 +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 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 86c51506c518ee445d00f7eef36ee2c9adbd9b4c..a37f392146ccc0319cf56ee0058ae8782b598fe3 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 {
@@ -509,8 +509,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 a config to enable tick command
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..9f43eff6160ac6855c2e5dd9c23c384b03b7e96c 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( // Lophine - Add tick rate support
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))
@@ -5,7 +5,7 @@ Subject: [PATCH] Spawn invulnerable time
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 338e0c7c09120c6e9617893dd074cbd5da40a093..baab2435bac22aacff30ad52bde629b4093bfaba 100644
index 5f1fad59a26e3fe29f9000a92be5d6c4422dcd01..f3afab1100a35cc9ab091944de93d1f30ef040a7 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -242,6 +242,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -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 0b5f2060062a354bd6cafa8f53a5734dc83d062d..e15be199d690954d99d710de4046e721a943b3a9 100644
index 47beff71ed33e7fbd6fe6cd47aa955233af41f04..8e5b79db12882432de575f2a76aa36eac6fc8f51 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 65d5c766eb9bfade4d8259bda418a7f0e413edbe..b052bc0107d93cd65a6c92914d6b3d02d6cc5ccb 100644
index fa588ab87f978b8aeaef0f1849aa532e5a4ad940..dd4a92a0ea94d16669535bde9b6728515dafe7f4 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
@@ -414,7 +414,7 @@ index 15ed625105539f402fb39275b292531fe388a7a0..2b97fd6af1c4956eb173b8c66c2a3efc
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(remaining);
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 06d55281bb782cc064255c7b56acd6cd332b9085..d926be9a0c4954746032e3e96cf50a8cba5f26b3 100644
index 72a258f046c67c8970c91b8da31c0e745ec1e7ae..86a13f11fa6730f85add3e2ff47781d0fbcae170 100644
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -397,7 +397,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
@@ -0,0 +1,186 @@
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)))
);
@@ -6,7 +6,7 @@ Subject: [PATCH] Compatibility fix for Raid Revert and Cross Region Damage
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index cc7b2ea7fda1326e3f9ed46373190a05f60c4d34..2bce20202b7c539bee3685741663a8ed225919ff 100644
index 29919b8f3c05c8ffaf66f86e441778eeefb293b1..1e820f34636f415ef78cdfbed06c6952a3cf1c0b 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1234,6 +1234,30 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -36,7 +36,7 @@ index e9f86409bf9351e85ed31e747d9350dbf0cc441f..1f8f4d979d8766d6ba385f74cf8fcf8e
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 82013a8f7cf07b6f0645ca6b51ee75fcb0a56298..54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e 100644
index 8dcd684189d953aabddc4f62a3ecc5807c949ce6..0bedaa20bc2cae75a48357e69740ada2380a03dd 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 0f1bd15ea3b1400cc948883c92eceabcd4a4cda1..006844d6fda43f3b151899655f03b1de03f3396c 100644
index c380ab9f059da6219691e8bccd4f82b9ec5483b3..b2ea90b0ab461d202d492411471d2412a9c5d303 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 ca35415e152dc63cb9f4ae8da8b06766600922fd..033715812acb8f98a7c7d895d115043e232d5161 100644
index afcab27006558f5d379df723968a612c1cadba60..ddab99a4cc70a1aa365208cb52d8d9b880cdeff6 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 ca35415e152dc63cb9f4ae8da8b06766600922fd..033715812acb8f98a7c7d895d115043e
+ // Leaves end - servux
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 006844d6fda43f3b151899655f03b1de03f3396c..0befa4fc81e10a23c6ba824e559f2fb4886e68ee 100644
index b2ea90b0ab461d202d492411471d2412a9c5d303..049339ae33569d627d2a00ef6cab9cad02c4c014 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 e15be199d690954d99d710de4046e721a943b3a9..0eae303f8959345571a906906ef60c6a28bba348 100644
index 8e5b79db12882432de575f2a76aa36eac6fc8f51..977a4ac391b8cf8b59c5c77becf9a5951d513526 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 da9706f866aabee6939cacbfbcc9def01fde0326..3708f9ffc46a5b1c038c0e7b2ce84802e2b22397 100644
index 4882df428369e87bcf23b532dd970b13b3adfb88..e51f99de547f09f98b9e351bf84d8411994b62bc 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -772,6 +772,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -757,6 +757,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 0eae303f8959345571a906906ef60c6a28bba348..1af966cadec3dd51aae842824e432e20b700d9c9 100644
index 977a4ac391b8cf8b59c5c77becf9a5951d513526..bc38b16dd296cca9bc5556b95117794e633a9c27 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 1af966cadec3dd51aae842824e432e20b700d9c9..83c9418ea45b8d7f639c6bf5e134bad90d9ac039 100644
index bc38b16dd296cca9bc5556b95117794e633a9c27..57aff87cc7be0cb7136689412490cd399eff15eb 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 c5f4e0570a82dfcc2ba88023f3301f69afa41cc5..30f7e8f5e3e9440713e36ee25c90150b6b93c6ff 100644
index 0cdd88e530c660b65f3eb331b37cbd2c69fc2ff5..62dec122c5e23150dc107d3fab5a552f86d34565 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 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc107923876045be29848 100644
index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a7546eb15 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,24 +45,15 @@ index 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc10792387604
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<>();
@@ -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
@@ -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
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
@@ -71,7 +62,7 @@ index 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc10792387604
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1827,6 +1839,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1827,6 +1830,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isSaving = true;
if (playerSaveInterval > 0) {
this.playerList.saveAll(playerSaveInterval);
@@ -79,7 +70,7 @@ index 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc10792387604
}
if (region == null && fullSave) { // Folia - region threading - don't auto save level data
this.saveGlobalData(false);
@@ -2065,6 +2078,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2065,6 +2069,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
protected void tickConnection() {
this.getConnection().tick();
@@ -87,7 +78,7 @@ index 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc10792387604
}
public void forceGameTimeSynchronization() {
@@ -3270,6 +3284,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -3270,6 +3275,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.debugSubscribers;
}
@@ -222,22 +213,6 @@ 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
@@ -277,7 +252,7 @@ index 0dfb25ad032429a2aea7aa441dd5fd1848a6c617..215f2a40921cc8e6b181c0a34aa1bbaf
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 0befa4fc81e10a23c6ba824e559f2fb4886e68ee..2ddcf6ae90aaaf98e2fcd8ab9995b6f0d7791856 100644
index 049339ae33569d627d2a00ef6cab9cad02c4c014..e05705884a285143b8a3ebad00cb489efe47d532 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
@@ -334,10 +309,19 @@ index 0befa4fc81e10a23c6ba824e559f2fb4886e68ee..2ddcf6ae90aaaf98e2fcd8ab9995b6f0
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index baab2435bac22aacff30ad52bde629b4093bfaba..cdb4a52cbd34322903144364c3686a4e1bf0fbb8 100644
index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00ce41c64bb 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -229,7 +229,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -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
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
public ServerGamePacketListenerImpl connection;
private final MinecraftServer server;
@@ -346,7 +330,7 @@ index baab2435bac22aacff30ad52bde629b4093bfaba..cdb4a52cbd34322903144364c3686a4e
private final PlayerAdvancements advancements;
private final ServerStatsCounter stats;
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
@@ -250,7 +250,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -250,7 +252,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private @Nullable Entity camera;
public boolean isChangingDimension;
public boolean seenCredits = false;
@@ -355,7 +339,7 @@ index baab2435bac22aacff30ad52bde629b4093bfaba..cdb4a52cbd34322903144364c3686a4e
private @Nullable Vec3 levitationStartPos;
private int levitationStartTime;
private boolean disconnected;
@@ -1514,7 +1514,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1514,7 +1516,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Luminol End - Cross Region Damage trace
@@ -364,12 +348,12 @@ index baab2435bac22aacff30ad52bde629b4093bfaba..cdb4a52cbd34322903144364c3686a4e
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
.getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS)
@@ -2180,6 +2180,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -2180,6 +2182,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 (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (FakeplayerConfig.enable) {
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
+ }
+ // Leaves end - bot support
@@ -442,15 +426,24 @@ 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..14be3d21cc1a613b1d9164ecc699073f0da2047c 100644
index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bbf6495770 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -319,6 +319,19 @@ public abstract class PlayerList {
@@ -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 {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (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);
@@ -465,19 +458,19 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -791,6 +804,11 @@ public abstract class PlayerList {
@@ -791,6 +806,11 @@ public abstract class PlayerList {
respawnReason
).callEvent();
// Paper end
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (FakeplayerConfig.enable) {
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
+ }
+ // Leaves end - bot support
return player;
}
@@ -893,11 +911,16 @@ public abstract class PlayerList {
@@ -893,11 +913,16 @@ public abstract class PlayerList {
public String[] getPlayerNamesArray() {
List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
@@ -495,7 +488,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f
return names;
}
@@ -1016,8 +1039,15 @@ public abstract class PlayerList {
@@ -1016,8 +1041,15 @@ public abstract class PlayerList {
|| this.allowCommandsForAllPlayers;
}
@@ -513,7 +506,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f
}
public void broadcast(
@@ -1360,7 +1390,13 @@ public abstract class PlayerList {
@@ -1360,7 +1392,13 @@ public abstract class PlayerList {
}
public @Nullable ServerPlayer getPlayer(final UUID uuid) {
@@ -529,7 +522,7 @@ index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f
public @Nullable ServerPlayer getPlayer(final String playerName) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index f090b8d77bd2731debfc61c263bd77550f52212b..03c155140da7300f6f934aff323e0daed1b63366 100644
index b69698f47ccb0f1ac3eeea05a02ab9d798319b44..b073a91fd67d092713c53db6f3df75c655dc8fcd 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1257,7 +1257,7 @@ public abstract class Entity
@@ -541,7 +534,7 @@ index f090b8d77bd2731debfc61c263bd77550f52212b..03c155140da7300f6f934aff323e0dae
this.checkFallDamage(movement.y, this.onGround(), effectState, effectPos);
}
@@ -1602,7 +1602,7 @@ public abstract class Entity
@@ -1593,7 +1593,7 @@ public abstract class Entity
return colliders.isEmpty() ? maxDistance : -Shapes.collide(Direction.Axis.Y, aabb, colliders, -maxDistance);
}
@@ -551,7 +544,7 @@ index f090b8d77bd2731debfc61c263bd77550f52212b..03c155140da7300f6f934aff323e0dae
final boolean xZero = movement.x == 0.0;
final boolean yZero = movement.y == 0.0;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 2bce20202b7c539bee3685741663a8ed225919ff..a2f44e4354f6aa1c0502cba40cadaad59193b169 100644
index 1e820f34636f415ef78cdfbed06c6952a3cf1c0b..8a8de7f4d62532709805ebde531dc71ad78fa5c9 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3347,7 +3347,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -597,7 +590,7 @@ index 2bce20202b7c539bee3685741663a8ed225919ff..a2f44e4354f6aa1c0502cba40cadaad5
if (!this.level().isClientSide()) {
boolean wasUsingItem = this.isUsingItem();
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index b45481f781f3556001af89704b718d6291ba1f66..2135ea645131c27b9bec5534431199f9d55134d8 100644
index f6f6d21f3393a3ab79a84212b0d66d83d0e817f1..38689fa466a20c64f9916ee32a57a9fdb58d9403 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -167,7 +167,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -719,7 +712,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 b052bc0107d93cd65a6c92914d6b3d02d6cc5ccb..fd2545f33692f964b62415178069e46e9c9d4c02 100644
index dd4a92a0ea94d16669535bde9b6728515dafe7f4..77f3bf9d9c0bb08a151adf1abd22e22d0fc83bf3 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 c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873c83c093f 100644
index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1930,7 +1930,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1921,7 +1921,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
private ServerStatus.Players buildPlayerStatus() {
@@ -96,7 +96,7 @@ index c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873
int maxPlayers = this.getMaxPlayers();
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
@@ -2151,7 +2151,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2142,7 +2142,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public int getPlayerCount() {
@@ -105,7 +105,7 @@ index c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873
}
public String[] getPlayerNames() {
@@ -2363,7 +2363,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2354,7 +2354,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} else {
int count = 0;
@@ -114,7 +114,7 @@ index c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873
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
@@ -2550,7 +2550,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2541,7 +2541,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 c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873
player.getAdvancements().save();
}
// Paper end - we don't need to save everything, just advancements
@@ -2686,7 +2686,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2677,7 +2677,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 2ddcf6ae90aaaf98e2fcd8ab9995b6f0d7791856..a7cebb797973cde399dc30c696b064efd40874f2 100644
index e05705884a285143b8a3ebad00cb489efe47d532..c51b0075cd650085cd991bc89396f605cb520442 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 2ddcf6ae90aaaf98e2fcd8ab9995b6f0d7791856..a7cebb797973cde399dc30c696b064ef
}
// Leaves end - skip
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1f82c9279 100644
index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41e33e775c 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -130,6 +130,7 @@ public abstract class PlayerList {
@@ -132,6 +132,7 @@ public abstract class PlayerList {
private int simulationDistance;
private boolean allowCommandsForAllPlayers;
private int sendAllPlayerInfoIn;
@@ -318,7 +318,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -191,6 +192,7 @@ public abstract class PlayerList {
@@ -193,6 +194,7 @@ public abstract class PlayerList {
private boolean countConnection(Connection conn, int limit) {
synchronized (this.connectionsStateLock) {
@@ -326,7 +326,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
int count = this.usersCountedAgainstLimit.size();
if (count >= limit) {
return false;
@@ -221,6 +223,124 @@ public abstract class PlayerList {
@@ -223,6 +225,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 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (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 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
public void placeNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -294,6 +414,7 @@ public abstract class PlayerList {
@@ -296,6 +416,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 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
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
@@ -513,6 +634,7 @@ public abstract class PlayerList {
@@ -515,6 +636,7 @@ public abstract class PlayerList {
}
protected void save(final ServerPlayer player) {
@@ -467,7 +467,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
player.lastSave = System.nanoTime(); // Folia - region threading - changed to nanoTime tracking
this.playerIo.save(player);
@@ -527,6 +649,47 @@ public abstract class PlayerList {
@@ -529,6 +651,47 @@ public abstract class PlayerList {
}
}
@@ -515,7 +515,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
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())));
@@ -600,6 +763,7 @@ public abstract class PlayerList {
@@ -602,6 +765,7 @@ public abstract class PlayerList {
player.getBukkitEntity().packetProcessor.close(); // Folia - region threading
player.getAdvancements().stopListening();
this.players.remove(player);
@@ -523,7 +523,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
this.server.getCustomBossEvents().onPlayerDisconnect(player);
UUID uuid = player.getUUID();
@@ -910,15 +1074,15 @@ public abstract class PlayerList {
@@ -912,15 +1076,15 @@ public abstract class PlayerList {
}
public String[] getPlayerNamesArray() {
@@ -546,7 +546,7 @@ index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1
// Leaves end - fakeplayer support
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index a2f44e4354f6aa1c0502cba40cadaad59193b169..a3c19d725e03c07de6708f3c2d092e0b9aea69c2 100644
index 8a8de7f4d62532709805ebde531dc71ad78fa5c9..167855ad90d0c168a6d49f078ee3409ab84d4bf3 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -261,7 +261,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -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 2135ea645131c27b9bec5534431199f9d55134d8..5e7e99410c7597ec5330cc82e441fa30c53c9532 100644
index 38689fa466a20c64f9916ee32a57a9fdb58d9403..7d514537ee38f9b9366692bc969ff503d883aa16 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 2135ea645131c27b9bec5534431199f9d55134d8..5e7e99410c7597ec5330cc82e441fa30
+ // Leaves start - creative no clip
+ public boolean isCreativeFlyOrSpectator() {
+ return isSpectator() || (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.creativeNoClip && isCreative() && getAbilities().flying);
+ return isSpectator() || (fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && 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 2135ea645131c27b9bec5534431199f9d55134d8..5e7e99410c7597ec5330cc82e441fa30
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..07b84bd0144e133d13e8e033a8998f3cf674f746 100644
index 2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f..06160c24f1ffbe1445284bc81598cabb3ad20477 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..07b84bd0144e133d13e8e033a8998f3c
+ 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.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
+ && ((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
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..596fb91fccb4c8d6854fa859f9ee357c6d22a81e 100644
index cb0a4a9865df69e5504a86de6c144bc4450bd19a..a40a98bb48bb14c49670ba55d2a2e8d7e9d0d178 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..596fb91fccb4c8d6854fa859f9ee357c
// CraftBukkit start
if (stateForPlacement != null) {
- boolean defaultReturn = level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty());
+ 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
+ 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
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 a7cebb797973cde399dc30c696b064efd40874f2..c0e62a69bb5c9e777265b5474d76ba8d06ccec4b 100644
index c51b0075cd650085cd991bc89396f605cb520442..fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54 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
@@ -114,7 +114,7 @@ index a7cebb797973cde399dc30c696b064efd40874f2..c0e62a69bb5c9e777265b5474d76ba8d
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
ProfilerFiller profiler = Profiler.get();
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index fc29654dd7ee3329edf1ccf705f45631d0ecc079..9b8ee2df5a0b6d76d9bfc747187f6cd51bb4a520 100644
index fc29654dd7ee3329edf1ccf705f45631d0ecc079..5cad076041ed008670cfd8e51a3601c2ef972ad1 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -813,6 +813,44 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
@@ -158,7 +158,7 @@ index fc29654dd7ee3329edf1ccf705f45631d0ecc079..9b8ee2df5a0b6d76d9bfc747187f6cd5
+ }
+ }
+ }
+ // Lophine end - fix some bug if player is cross scheduler >> to remove monster if the region don't have any valid player
+ // Lophine end
this.noActionTime = 0;
}
}
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 7 Feb 2026 23:57:50 +0800
Date: Tue, 2 Jun 2026 19:55:06 +0800
Subject: [PATCH] Leaves: Catch update suppression crash
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
@@ -8,22 +8,19 @@ 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/network/PacketProcessor.java b/net/minecraft/network/PacketProcessor.java
index 24f5b890b0126fc817863f99b676da1a548f7608..a25bc31c04778bf12e3b6301ffcfb2275fcc2d90 100644
index 24f5b890b0126fc817863f99b676da1a548f7608..78bea975c15130c91c90f48c868ac32e2db7433f 100644
--- a/net/minecraft/network/PacketProcessor.java
+++ b/net/minecraft/network/PacketProcessor.java
@@ -106,7 +106,23 @@ public class PacketProcessor implements AutoCloseable {
@@ -106,7 +106,19 @@ public class PacketProcessor implements AutoCloseable {
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(ListenerAndPacket.this.packet.getClass().getName())); try { // Folia - profiler
this.packet.handle(this.listener);
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ // Lophine end - catch update suppression crash
} catch (Exception var3) {
+ // Lophine start - catch update suppression crash
+ if (var3.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
@@ -31,29 +28,25 @@ index 24f5b890b0126fc817863f99b676da1a548f7608..a25bc31c04778bf12e3b6301ffcfb227
+ exception.consume();
+ }
+
+ // Lophine end - catch update suppression crash
if (var3 instanceof ReportedException re && re.getCause() instanceof OutOfMemoryError) {
throw PacketUtils.makeReportedException(var3, this.packet, this.listener);
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f99c02b4d88cea924e20ca8dced67873c83c093f..0c042c4af5d52c08e9fbc03a04c4b696d8a0a7ed 100644
index 48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3..06482d945e4f7b1adc56168ad43bea34484a6fa9 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2019,11 +2019,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2010,11 +2010,26 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler
level.tick(haveTime, region); // Folia - region threading
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(level);
+ exception.consume();
+ // Lophine end - catch update suppression crash
} finally { foliaProfiler.stopTimer(level.tickTimerId); } // Folia - profiler
} catch (Throwable var7) {
- CrashReport report = CrashReport.forThrowable(var7, "Exception ticking world");
- level.fillReportDetails(report);
- throw new ReportedException(report);
+ // Lophine start - catch update suppression crash
+ org.leavesmc.leaves.util.UpdateSuppressionException updateSuppressionException = null;
+ if (var7 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ updateSuppressionException = exception;
@@ -69,21 +62,19 @@ index f99c02b4d88cea924e20ca8dced67873c83c093f..0c042c4af5d52c08e9fbc03a04c4b696
+ level.fillReportDetails(report);
+ throw new ReportedException(report);
+ }
+ // Lophine end - catch update suppression crash
}
profiler.pop();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index c0e62a69bb5c9e777265b5474d76ba8d06ccec4b..3e7420cd98504732db17cb6b0fcfdfbb8deeb552 100644
index fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54..f44f772628f5705c5dee9cb92295362ba09c20ce 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -967,7 +967,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -967,7 +967,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
// Kaiiju end
profiler.push("tick");
- this.guardEntityTick(this::tickNonPassenger, entity);
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ try {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
@@ -93,37 +84,33 @@ index c0e62a69bb5c9e777265b5474d76ba8d06ccec4b..3e7420cd98504732db17cb6b0fcfdfbb
+ } else {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ }
+ // Lophine end - catch update suppression crash
profiler.pop();
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index cdb4a52cbd34322903144364c3686a4e1bf0fbb8..3a3a335a7659ebe946221186b56150df4a89c004 100644
index 7f6d4118ede7e02fdea8961fd736d00ce41c64bb..91ec7f6b751159f2935165268166f44d27579426 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1130,6 +1130,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1132,6 +1132,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
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.providePlayer(this);
+ exception.provideLevel(this.level());
+ exception.consume();
+ // Lophine end - catch update suppression crash
} catch (Throwable var4) {
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 03c155140da7300f6f934aff323e0daed1b63366..ee84484ca5aac03b9f321398c4d85311632b5697 100644
index b073a91fd67d092713c53db6f3df75c655dc8fcd..ba3eabe8208c45f8adbe431965a2d936fea93fdf 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1459,7 +1459,17 @@ public abstract class Entity
@@ -1450,7 +1450,15 @@ public abstract class Entity
}
if (shouldVibrate) {
- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, blockState));
+ // Lophine start - catch update suppression crash
+ try {
+ this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, blockState));
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
@@ -133,68 +120,62 @@ index 03c155140da7300f6f934aff323e0daed1b63366..ee84484ca5aac03b9f321398c4d85311
+ }
+ exception.consume();
+ }
+ // Lophine end - catch update suppression crash
}
return true;
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..f9dacc278200b05acb385e1f1cbf858e43d0d9f4 100644
index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..80d10b42106749254eb5f757986838acc1c064d2 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -181,7 +181,16 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -181,7 +181,14 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@Override
protected int getAnalogOutputSignal(final BlockState state, final Level level, final BlockPos pos, final Direction direction) {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine start - catch update suppression crash
+ try {
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ } catch (ClassCastException ex) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
+ }
+ throw ex;
+ }
+ // Lophine end - catch update suppression crash
}
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..5bf43973c8de8c2f33d384f28fdd06864cdf9319 100644
index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..a359d9ce555b9c8ec01ed71b305ab8efa80c3892 100644
--- a/net/minecraft/world/level/block/state/StateHolder.java
+++ b/net/minecraft/world/level/block/state/StateHolder.java
@@ -118,7 +118,16 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
@@ -118,7 +118,14 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
if (ret != null) {
return ret;
}
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ // Lophine start - catch update suppression crash
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ 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;
+ }
+ }
+ throw iae;
+ // Lophine end - catch update suppression crash
// Paper end - optimise blockstate property access
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 3708f9ffc46a5b1c038c0e7b2ce84802e2b22397..241c43170b5020c1521f43d349813586ba1f69a5 100644
index e51f99de547f09f98b9e351bf84d8411994b62bc..7e7292dd8fcb27fdb8e69e42e5383b6c22154747 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -400,6 +400,8 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -385,6 +385,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
return null;
} else {
Block newBlock = state.getBlock();
+ // Lophine start - catch update suppression crash
+ try {
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);
@@ -468,6 +470,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -453,6 +454,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
this.markUnsaved();
return oldState;
}
@@ -202,28 +183,24 @@ index 3708f9ffc46a5b1c038c0e7b2ce84802e2b22397..241c43170b5020c1521f43d349813586
+ exception.provideBlock(this.level, pos, newBlock);
+ throw exception;
+ }
+ // Lophine end - catch update suppression crash
}
}
}
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..6358787f3c7dcfa599b2949613236fa8de025096 100644
index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..44731e230869f0df058f6a426277befbb0d559e4 100644
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
@@ -87,9 +87,24 @@ public interface NeighborUpdater {
@@ -87,9 +87,20 @@ public interface NeighborUpdater {
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Spigot start
} catch (StackOverflowError ex) {
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, changedBlock, null, ex);
+ }
+ // Lophine end - catch update suppression crash
level.lastPhysicsProblem = pos.immutable();
// Spigot end
} catch (Throwable var9) {
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(level, pos, changedBlock);
+ throw exception;
@@ -231,7 +208,6 @@ index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..6358787f3c7dcfa599b2949613236fa8
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, changedBlock, null, var9);
+ }
+
+ // Lophine end - catch update suppression crash
CrashReport report = CrashReport.forThrowable(var9, "Exception while updating neighbours");
CrashReportCategory category = report.addCategory("Block being updated");
category.setDetail(
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 15 Nov 2025 01:12:39 +0800
Date: Tue, 2 Jun 2026 20:06:33 +0800
Subject: [PATCH] Leaves: CCE update suppression
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
@@ -8,19 +8,17 @@ 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 f9dacc278200b05acb385e1f1cbf858e43d0d9f4..722ce78461b2303f99493c309345697cfc98fb99 100644
index 80d10b42106749254eb5f757986838acc1c064d2..ffa76dc1338c6c892a42b2148f9f01c933660b98 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -183,7 +183,11 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -182,7 +182,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@Override
protected int getAnalogOutputSignal(final BlockState state, final Level level, final BlockPos pos, final Direction direction) {
// Lophine start - catch update suppression crash
try {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine start - configurable shulker CCE
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.shulkerBoxCCEReintroduced
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce
+ ? AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container)level.getBlockEntity(pos))
+ : AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine end - configurable shulker CCE
} catch (ClassCastException ex) {
if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
@@ -1,72 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Wed, 14 Jun 2023 12:07:07 +0800
Date: Tue, 2 Jun 2026 20:15:44 +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..db80f0b400c7356c5524ea799354e6c44de14700 100644
index 45e11737bc2558a4ebfffe133d43111f45dd7d16..b6005e5e60ac571396d584c7f4dec3975a6f9923 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -59,6 +59,11 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
@@ -59,6 +59,9 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ // Lophine start - redstone ignore upwards update
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
+ // Lophine end - redstone ignore upwards update
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..30a7208a698a8bd3ba8a08ace6f23b206d90f6a3 100644
index 759eb347299813c20226cc2fc5dc7718d12b7f56..66a05f099a263b0c9220f1416f3cf1221422cc20 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -179,7 +179,11 @@ public class RedStoneWireBlock extends Block {
@@ -179,7 +179,9 @@ public class RedStoneWireBlock extends Block {
final RandomSource random
) {
if (directionToNeighbour == Direction.DOWN) {
- return !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
+ // Lophine start - redstone ignore upwards update
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate
+ ? state
+ : !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
+ // Lophine end - redstone ignore upwards update
} else if (directionToNeighbour == Direction.UP) {
return this.getConnectionState(level, state, pos);
} else {
@@ -243,7 +247,10 @@ public class RedStoneWireBlock extends Block {
@@ -243,7 +245,8 @@ public class RedStoneWireBlock extends Block {
BlockPos relativePos = pos.relative(direction);
BlockState relativeState = level.getBlockState(relativePos);
if (canConnectUp) {
- boolean isPlaceableAbove = relativeState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, relativePos, relativeState);
+ // Lophine start - redstone ignore upwards update
+ boolean isPlaceableAbove = (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && relativeState.getBlock() instanceof TrapDoorBlock)
+ boolean isPlaceableAbove = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && relativeState.getBlock() instanceof TrapDoorBlock)
+ || this.canSurviveOn(level, relativePos, relativeState);
+ // Lophine end - redstone ignore upwards update
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..1985602b11a584fc70b1bb9ca4c643757d4c0ed3 100644
index d301ca4c91e75d715998aa7ed155fd44ccd64785..13928e667cfa36e2ebf45b30caf4c5be28f2f725 100644
--- a/net/minecraft/world/level/block/RepeaterBlock.java
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
@@ -70,6 +70,11 @@ public class RepeaterBlock extends DiodeBlock {
@@ -70,6 +70,9 @@ public class RepeaterBlock extends DiodeBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ // Lophine start - redstone ignore upwards update
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
+ // Lophine end - redstone ignore upwards update
if (directionToNeighbour == Direction.DOWN && !this.canSurviveOn(level, neighbourPos, neighbourState)) {
return Blocks.AIR.defaultBlockState();
} else {
@@ -1,32 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 17 Nov 2025 18:41:08 +0800
From: Bacteriawa <A3167717663@hotmail.com>
Date: Tue, 2 Jun 2026 20:32:47 +0800
Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..9911c70d89cfb43b803cab9bbe6eedd1142f59d6 100644
index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..dad62b80578f27cc39985ee6ded705bf3cc5d117 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -506,7 +506,7 @@ public final class RegionizedWorldData {
@@ -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 {
public long lastMidTickExecuteFailure;
// From Level
public boolean populating;
- public final CollectingNeighborUpdater neighborUpdater;
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater; // Lophine - Instant Block Updater
+ public final NeighborUpdater neighborUpdater;
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public final Map<BlockPos, CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
@@ -567,7 +567,11 @@ public final class RegionizedWorldData {
@@ -567,7 +569,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);
+ // Lophine start - Instant Block Updater
+ this.neighborUpdater = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.instantBlockUpdaterReintroduced
+ ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world)
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater
+ ? new InstantNeighborUpdater(world)
+ : new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
+ // Lophine end - Instant Block Updater
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);
@@ -38,10 +45,10 @@ index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..9911c70d89cfb43b803cab9bbe6eedd1
\ No newline at end of file
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 3e7420cd98504732db17cb6b0fcfdfbb8deeb552..257b440a0eea379433e9a249175c8eb16c37accb 100644
index f44f772628f5705c5dee9cb92295362ba09c20ce..ee10aceeddb59241e4b1d0bea021001787ea2f88 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1001,11 +1001,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
@@ -999,11 +999,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
// Paper - rewrite chunk system
profiler.pop();
profiler.push("debugSynchronizers");
@@ -50,7 +57,6 @@ index 3e7420cd98504732db17cb6b0fcfdfbb8deeb552..257b440a0eea379433e9a249175c8eb1
- .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
- } else {
- regionizedWorldData.neighborUpdater.setDebugListener(null); // Folia - region threading
+ // Lophine start - Instant Block Updater
+ if (regionizedWorldData.neighborUpdater instanceof net.minecraft.world.level.redstone.CollectingNeighborUpdater neighborUpdater) {
+ if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) {
+ neighborUpdater // Folia - region threading
@@ -58,7 +64,6 @@ index 3e7420cd98504732db17cb6b0fcfdfbb8deeb552..257b440a0eea379433e9a249175c8eb1
+ } else {
+ neighborUpdater.setDebugListener(null); // Folia - region threading
+ }
+ // Lophine end - Instant Block Updater
}
this.debugSynchronizers.tick(this.server.debugSubscribers());
@@ -1,11 +1,11 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:24:32 +0800
From: Bacteriawa <A3167717663@hotmail.com>
Date: Tue, 2 Jun 2026 20:37:27 +0800
Subject: [PATCH] Revert TrapDoorBlock changes form Paper
diff --git a/net/minecraft/world/level/block/TrapDoorBlock.java b/net/minecraft/world/level/block/TrapDoorBlock.java
index cfc8b668980e0cba74b3f0d42c4902eb6aa8b01e..f01894c230b1ae4add3e20329e8dc87571d2c793 100644
index cfc8b668980e0cba74b3f0d42c4902eb6aa8b01e..da4a39e3e8bf9672614a04fae9834a54555cc9f1 100644
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -133,31 +133,7 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
@@ -37,7 +37,7 @@ index cfc8b668980e0cba74b3f0d42c4902eb6aa8b01e..f01894c230b1ae4add3e20329e8dc875
- }
- if (open) {
- // Paper end - break redstone on trapdoors early
+ if (state.getValue(OPEN) != signal) { // Lophine - revert Paper trapdoor redstone handling
+ if (state.getValue(OPEN) != signal) {
state = state.setValue(OPEN, signal);
this.playSound(null, level, pos, signal);
}
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:35:13 +0800
From: Bacteriawa <A3167717663@hotmail.com>
Date: Tue, 2 Jun 2026 20:42:45 +0800
Subject: [PATCH] Leaves: Prevent loss of item drops due to update suppression
when breaking blocks
@@ -9,15 +9,14 @@ 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/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index e1de10e1a0ec221a1109a03d86fddf47b1c06a5f..71cc37515c268abd698896d514b66cb49859691c 100644
index e1de10e1a0ec221a1109a03d86fddf47b1c06a5f..d8cba057be61005d75b8c66910096aec148e2e2a 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -392,7 +392,18 @@ public class ServerPlayerGameMode {
@@ -392,7 +392,16 @@ public class ServerPlayerGameMode {
this.level.getCurrentWorldData().captureDrops = new java.util.ArrayList<>(); // Folia - region threading
// CraftBukkit end
BlockState adjustedState = block.playerWillDestroy(this.level, pos, state, this.player);
- boolean changed = this.level.removeBlock(pos, false);
+ // Lophine start - preserve drops before update suppression
+ boolean changed;
+ org.leavesmc.leaves.util.UpdateSuppressionException updateSuppressionException = null;
+ try {
@@ -28,19 +27,16 @@ index e1de10e1a0ec221a1109a03d86fddf47b1c06a5f..71cc37515c268abd698896d514b66cb4
+ updateSuppressionException.providePlayer(this.player);
+ changed = false;
+ }
+ // Lophine end - preserve drops before update suppression
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("server broke {} {} -> {}", pos, adjustedState, this.level.getBlockState(pos));
}
@@ -424,6 +435,11 @@ public class ServerPlayerGameMode {
@@ -424,6 +433,9 @@ public class ServerPlayerGameMode {
if (event.isDropItems()) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, bState, this.player, itemsToDrop); // Paper - capture all item additions to the world
}
+ // Lophine start - preserve drops before update suppression
+ if (updateSuppressionException != null) {
+ throw updateSuppressionException;
+ }
+ // Lophine end - preserve drops before update suppression
// Drop event experience
if (changed) {
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 23:26:27 +0800
From: Bacteriawa <A3167717663@hotmail.com>
Date: Tue, 2 Jun 2026 20:50:57 +0800
Subject: [PATCH] Leaves: Do not reset placed block on exception & Do not
prevent block entity and entity crash at LevelChunk
@@ -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 07b84bd0144e133d13e8e033a8998f3cf674f746..9c016e7d93e4c44ddf2df520e5c57d92a0e085b3 100644
index 06160c24f1ffbe1445284bc81598cabb3ad20477..ca3f31a72060f797115787302d32a019fa8243e0 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 07b84bd0144e133d13e8e033a8998f3cf674f746..9c016e7d93e4c44ddf2df520e5c57d92
// 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 241c43170b5020c1521f43d349813586ba1f69a5..316b8d45b0902b1bf01a77307e24fc9a47d1283b 100644
index 7e7292dd8fcb27fdb8e69e42e5383b6c22154747..b7ba4d8ed2cc65ba0e85a3cdf8b6568a7c9c02f1 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1017,12 +1017,6 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -1000,12 +1000,6 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
profiler.pop();
} catch (Throwable var5) {
@@ -522,10 +522,10 @@ index 6a3413ca875ce78f48cd8d3ce2cfe7798be1a19e..be572eff561ffdd961a9602eaa613676
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 30a7208a698a8bd3ba8a08ace6f23b206d90f6a3..7f5b77cd9cb78e693bbe1efd3d5fd7256d7700c5 100644
index 66a05f099a263b0c9220f1416f3cf1221422cc20..1de86856f4a27346d7003ca9eb24a36074a2a4a3 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -382,6 +382,28 @@ public class RedStoneWireBlock extends Block {
@@ -378,6 +378,28 @@ public class RedStoneWireBlock extends Block {
}
}
@@ -622,7 +622,7 @@ index d7e5ec23c64b60c47ab6b54cbf282e88c3a4a045..037aa3592a963bbb142465d31040f60e
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 722ce78461b2303f99493c309345697cfc98fb99..45dc3e8484842265b26d387d518831ff23da4b5e 100644
index ffa76dc1338c6c892a42b2148f9f01c933660b98..7bf2cde59c112f4babb87476585207dacebef341 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -150,6 +150,20 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -797,10 +797,10 @@ index 0fbdf810c785c8a596d461e7651361fdedbb6217..ff1471f40b73582df68efbf2996a854c
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 316b8d45b0902b1bf01a77307e24fc9a47d1283b..9b3775b0cbca782964e03935331d1bfdd1af140d 100644
index b7ba4d8ed2cc65ba0e85a3cdf8b6568a7c9c02f1..6b5ad391eda92cdbb47ab78a4c27d7e6a3b098a8 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -424,22 +424,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -408,22 +408,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;
@@ -1,48 +0,0 @@
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));
@@ -1,142 +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] Carpet Features Compatible
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 4bd923b42d1c98ce7178e05f9324f46d99ffc933..55bd9581c8c4bd3b1b7ba75cc80c94cf7548638a 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(); // Lophine - Carpet features
++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
@@ -531,7 +531,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 a37f392146ccc0319cf56ee0058ae8782b598fe3..2223f0b38e8f628af64d1c916fb2310c4704a407 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -576,7 +576,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 74ef76058e5a410d12f88aa09450e7d90f63b5e6..1761167da363cd074a26499caadeaeb916461706 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -268,7 +268,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 8ed9aa981883458d11f8cddce56e04b021026cc2..fb200adb544a9cc5eb7d9d0051a6c70da017b858 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2188,7 +2188,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 ac5b419169f8574f92ff7195bfa76c9978bc8a63..8066cdcaba8d2fcfa2e9ba3b040a2867dbbc6978 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;
}
@@ -668,7 +668,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..125d5f59bdfdee5aa4bae2aa4756db363ee17f4b 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) { // Lophine - Carpet Features Compatible
int i, j;
for (i = cachePortalChunkIteratorX; i <= 8; ++i) {
for (j = cachePortalChunkIteratorZ; j <= 8; ++j) {
@@ -50,7 +50,7 @@ index a5f2e4454258886536251288c3694f58386c7420..28371ecf31d5fc280aaa03ed9a86f5b5
private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://papermc.io)";
private static final Gson GSON = new Gson();
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
index 4ada790812957657d580cb748077c4961987d0cb..ddf3ad20e7ce967d9e096345f99c55abf066c3b3 100644
index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5effe76734b4 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
@@ -31,7 +31,7 @@ public record ServerBuildInfoImpl(
@@ -58,7 +58,7 @@ index 4ada790812957657d580cb748077c4961987d0cb..ddf3ad20e7ce967d9e096345f99c55ab
private static final String BRAND_PAPER_NAME = "Paper";
- private static final String BRAND_LUMINOL_NAME = "Luminol";
+ private static final String BRAND_LOPHINE_NAME = "Lophine"; // Lophine - Rebrand to Lophine
+ private static final String BRAND_LOPHINE_NAME = "Lophine";
private static final String BUILD_DEV = "DEV";
@@ -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 ba0779211405b8b83f7c7e7b1c55b3e4846029a3..5f685b07878443bfe5f63147a0728df0708d79ad 100644
index 20bebf72768968d90f27f812456796cf81f46626..479bbc4a63c237c055f6b4d659c598e9fadd512a 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..d0b763f07aee56f69a67c87d7dd15a44b6f44db7 100644
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6f9f62263 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..d0b763f07aee56f69a67c87d7dd15a44
// SimplePluginManager
public void callEvent(@NotNull Event event) {
+ // Leaves start - process bot load/save
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled() && fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig.fakePlayerResident) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable && fun.bm.lophine.config.modules.function.FakeplayerConfig.canResident) {
+ 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 5f685b07878443bfe5f63147a0728df0708d79ad..0eb89fc127738e02e8d4d49418b83baaffe00cbd 100644
index 479bbc4a63c237c055f6b4d659c598e9fadd512a..054d9f4a09035771a329d6d561249d206b5dbee3 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 5f685b07878443bfe5f63147a0728df0708d79ad..0eb89fc127738e02e8d4d49418b83baa
return false;
}
@@ -3113,6 +3115,13 @@ public final class CraftServer implements Server {
@@ -3055,6 +3057,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 d0b763f07aee56f69a67c87d7dd15a44b6f44db7..bd301425f4c3cdf2b2bd22c1775b7ca9be1d4248 100644
index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 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 d0b763f07aee56f69a67c87d7dd15a44b6f44db7..bd301425f4c3cdf2b2bd22c1775b7ca9
}
// 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 0eb89fc127738e02e8d4d49418b83baaffe00cbd..53e49df883ec0fab984f2329d044d12ed6b1edff 100644
index 054d9f4a09035771a329d6d561249d206b5dbee3..8fc75ef37f273433fb11cc1e0beee87484c3e18f 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 0eb89fc127738e02e8d4d49418b83baaffe00cbd..53e49df883ec0fab984f2329d044d12e
@Override
public CraftPlayer apply(ServerPlayer player) {
return player.getBukkitEntity();
@@ -3186,4 +3187,11 @@ public final class CraftServer implements Server {
@@ -3128,4 +3129,11 @@ public final class CraftServer implements Server {
}
}
// Folia end - region TPS API
@@ -1,10 +1,20 @@
/*
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.carpet.config.modules.WoolHopperCounterConfig;
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.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;
@@ -14,11 +24,42 @@ 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);
}
@@ -79,7 +120,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", FakeplayerConfig.enable));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "commandBot", FakePlayerCompatConfig.commandBot));
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));
@@ -92,7 +133,8 @@ 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", WoolHopperCounterConfig.hopperCounters));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", WoolHopperCounterConfig.hopperCountersUnlimitedSpeed));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "hopperCounters", CounterCompatConfig.hopperCounters));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", CounterCompatConfig.hopperCountersUnlimitedSpeed));
}
}
*/
@@ -1,8 +1,6 @@
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;
@@ -26,10 +24,9 @@ import java.util.WeakHashMap;
public final class LagFreeSpawningCompatHelper {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Map<RegionizedWorldData, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
private static final Map<ServerLevel, 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);
@@ -87,22 +84,15 @@ public final class LagFreeSpawningCompatHelper {
}
public static @Nullable Mob getOrCreateMob(ServerLevel level, EntityType<?> entityType) {
RegionizedWorldData data = level.getCurrentWorldData();
if (data == null) return createMob(level, entityType);
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level.getCurrentWorldData(), key -> new HashMap<>());
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level, 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) {
PRECOOKED_MOBS.get(level.getCurrentWorldData()).put(entityType, created);
cache.put(entityType, created);
return created;
}
LOGGER.warn("Can't precook non-mob entity type: {}", entityType);
@@ -114,7 +104,7 @@ public final class LagFreeSpawningCompatHelper {
}
public static void markSpawned(ServerLevel level, EntityType<?> entityType) {
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level.getCurrentWorldData());
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level);
if (cache != null) {
cache.remove(entityType);
}
@@ -1,162 +0,0 @@
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) {
}
}
}
@@ -0,0 +1,30 @@
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();
}
}
@@ -0,0 +1,24 @@
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,15 +1,9 @@
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,
@@ -20,9 +14,12 @@ import java.util.Set;
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 = """
Enable /player command.(not remapped)
If you want to enable bot command, please see lophine global config.""")
Map Carpet's commandPlayer rule to the same fakeplayer command surface used by /bot.""")
public static boolean commandPlayer = false;
@ConfigInfo(name = "fakePlayerResident", comments = """
@@ -64,23 +61,4 @@ 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,11 +1,8 @@
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;
@@ -19,47 +16,40 @@ 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.
ATTENTION: This config will not update in Lophine global now!""")
Carpet language value forwarded to lophine.function.language.lang.""")
public static String language = "en_us";
@ConfigInfo(name = "amsUpdateSuppressionCrashFix", comments = """
Update suppression crash protection.""")
Map AMS update suppression crash protection to Lophine's existing crash fix.""")
public static boolean amsUpdateSuppressionCrashFix = false;
@ConfigInfo(name = "yeetUpdateSuppressionCrash", comments = """
Update suppression crash yeeting.""")
Map TIS update suppression crash yeeting to the same Lophine crash fix.""")
public static boolean yeetUpdateSuppressionCrash = false;
@ConfigInfo(name = "dustTrapdoorReintroduced", 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.""")
Map dust-on-open-trapdoor behavior to Lophine's redstone-ignore-upwards-update option.""")
public static boolean dustTrapdoorReintroduced = false;
@ConfigInfo(name = "shulkerBoxCCEReintroduced", comments = """
Use ClassCastException for update suppression.""")
Map shulker-box CCE update suppression to Lophine's cce-update-suppression option.""")
public static boolean shulkerBoxCCEReintroduced = false;
@ConfigInfo(name = "instantBlockUpdaterReintroduced", comments = """
Instant block updater.""")
Enable the existing instant block updater patch already carried by Lophine.""")
public static boolean instantBlockUpdaterReintroduced = false;
@ConfigInfo(name = "commandTick", comments = """
Enable the tick command support.""")
Enable the tick command support already patched into Lophine.""")
public static boolean commandTick = false;
@ConfigInfo(name = "creativeNoClip", 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.""")
Enable the existing creative fly no clip implementation.""")
public static boolean creativeNoClip = false;
@ConfigInfo(name = "optimizedDragonRespawn", comments = """
Enable optimized dragon respawn.""")
Enable the existing optimized dragon respawn implementation from Luminol.""")
public static boolean optimizedDragonRespawn = false;
@ConfigInfo(name = "antiSpamDisabled", comments = """
@@ -123,22 +113,6 @@ 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;
@@ -255,10 +229,6 @@ 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);
}
@@ -266,13 +236,4 @@ 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();
}
}
@@ -1,16 +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.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;
}
@@ -7,10 +7,10 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "command")
public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "trigger_command_enabled", comments =
@ConfigInfo(name = "tick_command_enabled", comments =
"""
Allow to use trigger command""")
public static boolean trigger = false;
Allow to use tick command""")
public static boolean tick = false;
@ConfigInfo(name = "function_command_enabled", comments =
"""
@@ -17,4 +17,11 @@ public class GlobalEntitiesCounter implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "async", comments = "Enable Asynchronous(maybe cause bugs)")
public static boolean async = false;
@HotReloadUnsupported
@ConfigInfo(name = "always_count", comments = """
Always count entities.
If you want to count entities loaded by chunk loader,
you must to enabled it.""")
public static boolean alwaysCount = false;
}
@@ -3,6 +3,8 @@ 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;
/*
@@ -11,6 +13,20 @@ 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;
}
@@ -0,0 +1,25 @@
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,11 +1,9 @@
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;
@@ -17,7 +15,7 @@ import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(name = "enable", comments = """
Enable fakeplayer functionality (/bot command)""")
Enable fakeplayer functionality""")
public static boolean enable = true;
@ConfigInfo(name = "unable-fakeplayer-names", comments = """
@@ -40,6 +38,14 @@ 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;
@@ -75,35 +81,28 @@ 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("bot");
command = new BotCommand();
command.register();
registered = true;
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (command != null) {
if (registered) {
command.unregister();
command = null;
}
@@ -11,9 +11,7 @@ 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
ATTENTION: If you want to edit language for carpet ststem,
please edit it in carpet config file.""")
Sample of format: en_us zh_cn zh_hk zh_tw""")
public static String lang = "en_us";
@ConfigInfo(name = "full_blocking_load", comments = """
@@ -1,4 +1,4 @@
package fun.bm.lophine.carpet.config.modules;
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.command.counter.CounterCommand;
@@ -11,29 +11,20 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "hopper_counter",
directory = {"carpet"},
comments = """
Hopper counter functions."""
)
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
public class WoolHopperCounterConfig implements IConfigModule {
@ConfigInfo(name = "hopperCounters", comments = """
Enable the existing wool hopper counter implementation.""")
public static boolean hopperCounters = false;
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
Remove the hopper transfer speed limit for counters.
Only effective when hopperCounters is enabled.""")
public static boolean hopperCountersUnlimitedSpeed = false;
@ConfigInfo(name = "unlimited-speed")
public static boolean unlimitedSpeed = false;
@DoNotLoad
private static CounterCommand counterCommand = null;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (hopperCounters) {
if (enabled) {
if (counterCommand == null) {
counterCommand = new CounterCommand();
}
@@ -8,7 +8,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@TransformedConfig(name = "always_count", directory = {"experiment", "global_entities_counter"})
@TransformedConfig(name = "enabled", directory = {"misc", "auto_update"})
@ConfigInfo(name = "removed", comments =
"""
@@ -3,34 +3,34 @@ package fun.bm.lophine.utils.concurrent;
import java.util.List;
import java.util.Map;
public interface AbstractConcurrentTable<X, Y, Z> {
void put(X x, Y y, Z z);
public abstract class AbstractConcurrentTable<X, Y, Z> {
public abstract void put(X x, Y y, Z z);
void remove(X x, Y y, Z z);
public abstract void remove(X x, Y y, Z z);
List<Z> getZ(X x, Y y);
public abstract List<Z> getZ(X x, Y y);
List<Y> getY(X x, Z z);
public abstract List<Y> getY(X x, Z z);
List<X> getX(Y y, Z z);
public abstract List<X> getX(Y y, Z z);
Map<X, Y> getXY(Z z);
public abstract Map<X, Y> getXY(Z z);
Map<Y, Z> getYZ(X x);
public abstract Map<Y, Z> getYZ(X x);
Map<X, Z> getXZ(Y y);
public abstract Map<X, Z> getXZ(Y y);
List<X> getAllX();
public abstract List<X> getAllX();
List<Y> getAllY();
public abstract List<Y> getAllY();
List<Z> getAllZ();
public abstract List<Z> getAllZ();
void clearXY(Z z);
public abstract void clearXY(Z z);
void clearYZ(X x);
public abstract void clearYZ(X x);
void clearXZ(Y y);
public abstract void clearXZ(Y y);
void clearAll();
public abstract 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> implements AbstractConcurrentTable<X, Y, Z> {
public class ConcurrentTable<X, Y, Z> extends 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> implements AbstractConcurrentTable<X, Y, Z
@Override
public void remove(X x, Y y, Z z) {
data.removeIf(entry -> entry.x().equals(x) && entry.y().equals(y) && entry.z().equals(z));
data.removeIf(entry -> entry.getX().equals(x) && entry.getY().equals(y) && entry.getZ().equals(z));
}
@Override
public List<Z> getZ(X x, Y y) {
return filterAndCollect(
entry -> entry.x().equals(x) && entry.y().equals(y),
TableEntry::z
entry -> entry.getX().equals(x) && entry.getY().equals(y),
TableEntry::getZ
);
}
@Override
public List<Y> getY(X x, Z z) {
return filterAndCollect(
entry -> entry.x().equals(x) && entry.z().equals(z),
TableEntry::y
entry -> entry.getX().equals(x) && entry.getZ().equals(z),
TableEntry::getY
);
}
@Override
public List<X> getX(Y y, Z z) {
return filterAndCollect(
entry -> entry.y().equals(y) && entry.z().equals(z),
TableEntry::x
entry -> entry.getY().equals(y) && entry.getZ().equals(z),
TableEntry::getX
);
}
@Override
public Map<X, Y> getXY(Z z) {
return filterAndMap(
entry -> entry.z().equals(z),
TableEntry::x,
TableEntry::y
entry -> entry.getZ().equals(z),
TableEntry::getX,
TableEntry::getY
);
}
@Override
public Map<Y, Z> getYZ(X x) {
return filterAndMap(
entry -> entry.x().equals(x),
TableEntry::y,
TableEntry::z
entry -> entry.getX().equals(x),
TableEntry::getY,
TableEntry::getZ
);
}
@Override
public Map<X, Z> getXZ(Y y) {
return filterAndMap(
entry -> entry.y().equals(y),
TableEntry::x,
TableEntry::z
entry -> entry.getY().equals(y),
TableEntry::getX,
TableEntry::getZ
);
}
@Override
public List<X> getAllX() {
return collectAll(TableEntry::x);
return collectAll(TableEntry::getX);
}
@Override
public List<Y> getAllY() {
return collectAll(TableEntry::y);
return collectAll(TableEntry::getY);
}
@Override
public List<Z> getAllZ() {
return collectAll(TableEntry::z);
return collectAll(TableEntry::getZ);
}
@Override
public void clearXY(Z z) {
data.removeIf(entry -> entry.z().equals(z));
data.removeIf(entry -> entry.getZ().equals(z));
}
@Override
public void clearYZ(X x) {
data.removeIf(entry -> entry.x().equals(x));
data.removeIf(entry -> entry.getX().equals(x));
}
@Override
public void clearXZ(Y y) {
data.removeIf(entry -> entry.y().equals(y));
data.removeIf(entry -> entry.getY().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.x(), entry.y(), entry.z());
removeFromIndex(yzIndex, entry.y(), entry.z(), entry.x());
removeFromIndex(zxIndex, entry.z(), entry.x(), entry.y());
removeFromIndex(xyIndex, entry.getX(), entry.getY(), entry.getZ());
removeFromIndex(yzIndex, entry.getY(), entry.getZ(), entry.getX());
removeFromIndex(zxIndex, entry.getZ(), entry.getX(), entry.getY());
}
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.x(), x) &&
Objects.equals(entry.y(), y) &&
Objects.equals(entry.z(), z))) {
Objects.equals(entry.getX(), x) &&
Objects.equals(entry.getY(), y) &&
Objects.equals(entry.getZ(), z))) {
return false;
}
put(x, y, z);
@@ -1,4 +1,25 @@
package fun.bm.lophine.utils.concurrent;
public record TableEntry<X, Y, Z>(X x, Y y, Z z) {
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;
}
}
@@ -22,7 +22,6 @@ 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;
@@ -51,12 +50,10 @@ 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.*;
@@ -103,7 +100,7 @@ public class BotList {
}
public void saveAllResumeBots() {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
return;
}
for (ServerBot bot : this.bots) {
@@ -193,11 +190,7 @@ 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);
@@ -354,7 +347,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, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
}
}
}
@@ -364,9 +357,9 @@ public class BotList {
AtomicInteger check = new AtomicInteger();
AtomicInteger received = new AtomicInteger();
for (ServerBot bot : this.bots) {
bot.resume = FakePlayerCompatConfig.fakePlayerResident;
bot.resume = FakeplayerConfig.canResident;
if (TickThread.isTickThreadFor(bot.level(), bot.getX(), bot.getZ())) {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
} else {
finished = false;
check.getAndIncrement();
@@ -383,7 +376,7 @@ public class BotList {
}
counter.getAndIncrement();
try {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakePlayerCompatConfig.fakePlayerResident, FakePlayerCompatConfig.fakePlayerResident);
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident, FakeplayerConfig.canResident);
received.getAndIncrement();
} catch (Exception e) {
this.removeBot(bot, check, received, counter);
@@ -396,7 +389,7 @@ public class BotList {
}
public void loadResumeBotInfo() {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
return;
}
CompoundTag savedBotList = this.getResumeBotList().copy();
@@ -432,7 +425,7 @@ public class BotList {
}
public void loadResume(String worldUuid) {
if (!FakeplayerConfig.checkEnabled() || !FakePlayerCompatConfig.fakePlayerResident) {
if (!FakeplayerConfig.enable || !FakeplayerConfig.canResident) {
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 (FakePlayerCompatConfig.openFakePlayerInventory) {
if (FakeplayerConfig.canOpenInventory) {
if (player instanceof ServerPlayer player1 && player.getMainHandItem().isEmpty()) {
BotInventoryOpenEvent event = new BotInventoryOpenEvent(this.getBukkitEntity(), player1.getBukkitEntity());
getServer().server.getPluginManager().callEvent(event);
@@ -417,31 +417,23 @@ public class ServerBot extends ServerPlayer {
super.readAdditionalSaveData(nbt);
this.setShiftKeyDown(nbt.getBooleanOr("isShiftKeyDown", false));
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);
CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC).orElseThrow();
BotCreateState.Builder createBuilder = BotCreateState
.builder(rawName, null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version
.name(name);
.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());
String[] skin = null;
if (createNbt.contains("skin")) {
ListTag skinTag = createNbt.getList("skin")
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin list"));
ListTag skinTag = createNbt.getList("skin").orElseThrow();
skin = new String[skinTag.size()];
for (int i = 0; i < skinTag.size(); i++) {
final int skinIndex = i;
skin[i] = skinTag.getString(i)
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin entry at index " + skinIndex));
skin[i] = skinTag.getString(i).orElseThrow();
}
}
createBuilder.skinName(skinName).skin(skin);
createBuilder.skinName(createNbt.getString("skinName").orElseThrow()).skin(skin);
createBuilder.createReason(BotCreateEvent.CreateReason.INTERNAL).creator(null);
this.createState = createBuilder.build();
@@ -451,17 +443,11 @@ 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 -> {
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);
AbstractBotAction<?> action = Actions.getForName(actionTag.getString("actionName").orElseThrow());
if (action != null) {
AbstractBotAction<?> newAction = action.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
});
}
@@ -469,16 +455,10 @@ 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) {
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);
AbstractBotConfig<?, ?> config = Configs.getConfig(configTag.getString("configName").orElseThrow());
if (config != null) {
config.setBot(this);
config.load(configTag);
}
}
}
@@ -31,12 +31,7 @@ import org.jetbrains.annotations.Nullable;
public class ServerBotPacketListenerImpl extends ServerGamePacketListenerImpl {
public ServerBotPacketListenerImpl(MinecraftServer server, ServerBot bot) {
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);
super(server, BotConnection.INSTANCE, bot, CommonListenerCookie.createInitial(bot.gameProfile, false));
}
@Override
@@ -58,14 +53,12 @@ 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() {
}
@@ -21,9 +21,9 @@ import com.mojang.brigadier.arguments.BoolArgumentType;
import fun.bm.lophine.LophineLogger;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import me.earthme.luminol.config.modules.experiment.CommandConfig;
import me.earthme.luminol.utils.FoliaServerWaypointManager;
import me.earthme.luminol.utils.NullPlugin;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.waypoints.ServerWaypointManager;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
@@ -53,7 +53,7 @@ public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfi
}
if (this.bot != null) {
this.value = value;
ServerWaypointManager manager = this.bot.level().getWaypointManager(); // Lophine - waypoint for adapt of luminol ver
FoliaServerWaypointManager manager = this.bot.level().getWaypointManager(); // Lophine - waypoint for adapt of luminol ver
if (value) {
manager.trackWaypoint(this.bot);
} else {
@@ -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(String key) {
super(key, PERM_BASE);
public BotCommand() {
super("bot", PERM_BASE);
this.children(
ListCommand::new,
ConfigCommand::new,
@@ -45,7 +45,6 @@ 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<>();
@@ -218,8 +217,8 @@ public class LeavesProtocolManager {
try {
return codec.decode(ProtocolUtils.decorate(buf));
} catch (Exception e) {
LOGGER.warn("Rejected malformed Leaves payload {}", location, e);
return INVALID_PAYLOAD;
LOGGER.error("Failed to decode payload {}", location, e);
throw e;
}
}
@@ -239,16 +238,9 @@ 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) {
try {
holder.invoke(selector, payload);
} catch (RuntimeException exception) {
LOGGER.warn("Rejected malformed Leaves payload {} from {}", payload.getClass().getName(), describeSelector(selector), exception);
}
holder.invoke(selector, payload);
}
}
@@ -256,47 +248,24 @@ public class LeavesProtocolManager {
RegistryFriendlyByteBuf buf1 = ProtocolUtils.decorate(buf);
BytebufReceiverInvokerHolder holder;
if ((holder = STRICT_BYTEBUF_RECEIVERS.get(location.toString())) != null) {
safeInvokeBytebuf(holder, selector, location, buf1);
holder.invoke(selector, buf1);
return true;
}
if ((holder = NAMESPACED_BYTEBUF_RECEIVERS.get(location.getNamespace())) != null) {
if (safeInvokeBytebuf(holder, selector, location, buf1)) {
if (holder.invoke(selector, buf1)) {
return true;
}
}
for (var holder1 : GENERIC_BYTEBUF_RECEIVERS) {
if (safeInvokeBytebuf(holder1, selector, location, buf1)) {
if (holder1.invoke(selector, 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() {
float interval = MinecraftServer.getServer().tickRateManager().millisecondsPerTick();
long currentTime = interval >= 1 ? System.currentTimeMillis() / (long) MinecraftServer.getServer().tickRateManager().millisecondsPerTick() : (long) (System.currentTimeMillis() / MinecraftServer.getServer().tickRateManager().millisecondsPerTick());
long currentTime = System.currentTimeMillis() / MinecraftServer.getServer().tickRateManager().nanosecondsPerTick();
if (currentTime == lastAcceptTime) return;
lastAcceptTime = currentTime;
for (var tickerInfo : TICKERS) {
@@ -445,4 +414,4 @@ public class LeavesProtocolManager {
}
}
}
}
}
@@ -46,7 +46,7 @@ public class ProtocolUtils {
private static final byte[] EMPTY = new byte[0];
public static String buildProtocolVersion(String protocol) {
return protocol + "-lophine-" + ServerBuildInfo.buildInfo().asString(ServerBuildInfo.StringRepresentation.VERSION_SIMPLE);
return protocol + "-leaves-" + ServerBuildInfo.buildInfo().asString(ServerBuildInfo.StringRepresentation.VERSION_SIMPLE);
}
public static void sendEmptyPacket(ServerPlayer player, Identifier id) {
@@ -400,25 +400,15 @@ 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) {
if (!(t instanceof CompoundTag compoundTag)) {
throw new IllegalStateException("Invalid REI input entry");
}
if (compoundTag.getInt("Index").isEmpty()) {
throw new IllegalStateException("Missing REI input index");
}
CompoundTag compoundTag = (CompoundTag) t;
compoundTag.getInt("Index").orElseThrow();
ListTag ingredientList = compoundTag.getListOrEmpty("Ingredient");
List<ItemStack> slotItems = new ArrayList<>();
for (Tag ingredient : ingredientList) {
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");
}
CompoundTag ingredientTag = (CompoundTag) ingredient;
ItemStack stack = ItemStack.OPTIONAL_CODEC.parse(
registryAccess.createSerializationContext(NbtOps.INSTANCE),
value
ingredientTag.get("value")
).getOrThrow();
slotItems.add(stack);
}
@@ -430,28 +420,16 @@ 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) {
if (!(t instanceof CompoundTag compoundTag)) {
throw new IllegalStateException("Invalid REI slot entry");
}
String id = compoundTag.getString("id").orElseThrow(() -> new IllegalStateException("Missing REI slot id"));
CompoundTag compoundTag = (CompoundTag) t;
String id = compoundTag.getString("id").orElseThrow();
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(() -> new IllegalStateException("Missing REI slot index"));
int slot = compoundTag.getInt("Slot").orElseThrow();
SlotAccessor accessor = switch (id) {
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);
}
case "vanilla" -> new VanillaSlotAccessor(menu.slots.get(slot));
case "player" -> new PlayerInventorySlotAccessor(player, slot);
default -> throw new IllegalStateException("Unknown container id: " + id);
};
slots.add(accessor);
@@ -345,8 +345,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
PACKET_C2S_STRUCTURES_UNREGISTER(4),
PACKET_S2C_STRUCTURE_DATA_START(5),
PACKET_S2C_SPAWN_METADATA(10),
PACKET_C2S_REQUEST_SPAWN_METADATA(11),
PACKET_S2C_WEATHER_DATA(12);
PACKET_C2S_REQUEST_SPAWN_METADATA(11);
public final int type;
@@ -51,21 +51,17 @@ 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.getIntOr("MinecraftDataVersion", SharedConstants.getProtocolVersion());
final int minecraftDataVersion = nbt.contains("MinecraftDataVersion") ? nbt.getInt("MinecraftDataVersion").orElseThrow() : 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");
@@ -120,7 +116,6 @@ 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;
@@ -146,9 +141,6 @@ 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);
@@ -163,19 +155,6 @@ 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();
@@ -299,4 +278,4 @@ public record LitematicaSchematic(Map<String, SubRegion> subRegions, SchematicMe
this.nbt = nbt;
}
}
}
}
@@ -264,17 +264,12 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
}
if (tags.getStringOr("Task", "").equals("LitematicaPaste")) {
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);
}
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);
}
}
@@ -443,4 +438,4 @@ public class ServuxLitematicsProtocol implements LeavesProtocol {
return !this.hasBuffer() && !this.hasNbt();
}
}
}
}
@@ -20,6 +20,7 @@ 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 {
/**
@@ -46,19 +47,11 @@ 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;
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];
}
this.longArray = Objects.requireNonNullElseGet(longArrayIn, () -> new long[(int) (roundUp(arraySizeIn * bitsPerEntryIn, 64L) / 64L)]);
}
public static long roundUp(long value, long interval) {
@@ -78,7 +71,6 @@ 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);
@@ -93,7 +85,6 @@ 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);
@@ -110,10 +101,4 @@ 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,9 +49,7 @@ public interface LitematicaBlockStatePalette {
final int size = tagList.size();
for (int i = 0; i < size; ++i) {
final int paletteIndex = i;
CompoundTag tag = tagList.getCompound(i)
.orElseThrow(() -> new IllegalArgumentException("Invalid block state palette entry at index " + paletteIndex));
CompoundTag tag = tagList.getCompound(i).orElseThrow();
BlockState state = NbtUtils.readBlockState(lookup, tag);
if (i > 0 || state != LitematicaBlockStateContainer.AIR_BLOCK_STATE) {
@@ -61,4 +59,4 @@ public interface LitematicaBlockStatePalette {
}
ListTag writeToNBT();
}
}
@@ -42,10 +42,7 @@ import org.leavesmc.leaves.protocol.servux.litematics.selection.Box;
import org.leavesmc.leaves.protocol.servux.litematics.utils.*;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
@@ -65,31 +62,20 @@ 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")),
origin,
NbtUtils.readBlockPosFromArrayTag(tags, "Origin"),
tags.getStringOr("Name", "")
);
placement.mirror = enumByOrdinal(Mirror.values(), tags.getIntOr("Mirror", 0), "Mirror");
placement.rotation = enumByOrdinal(Rotation.values(), tags.getIntOr("Rotation", 0), "Rotation");
placement.mirror = Mirror.values()[tags.getIntOr("Mirror", 0)];
placement.rotation = Rotation.values()[tags.getIntOr("Rotation", 0)];
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", "?"),
pos,
enumByOrdinal(Rotation.values(), compound.getIntOr("Rotation", 0), "SubRegions." + name + ".Rotation"),
enumByOrdinal(Mirror.values(), compound.getIntOr("Mirror", 0), "SubRegions." + name + ".Mirror"),
NbtUtils.readBlockPosFromArrayTag(compound, "Pos"),
Rotation.values()[compound.getIntOr("Rotation", 0)],
Mirror.values()[compound.getIntOr("Mirror", 0)],
compound.getBooleanOr("Enabled", true),
compound.getBooleanOr("IgnoreEntities", false)
);
@@ -98,13 +84,6 @@ 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;
@@ -323,13 +302,7 @@ public class SchematicPlacement {
AtomicInteger count_full = new AtomicInteger();
AtomicInteger count = new AtomicInteger();
BlockBox vanillaBox = enclosingBox.toVanilla();
if (vanillaBox == null) {
ServuxProtocol.LOGGER.error("receiver a null vanilla enclosing box");
return;
}
streamChunkPos(vanillaBox).forEach(chunkPos -> {
streamChunkPos(Objects.requireNonNull(enclosingBox.toVanilla())).forEach(chunkPos -> {
RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
serverWorld,
chunkPos.x(),
@@ -51,7 +51,6 @@ 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<>();
@@ -88,11 +87,7 @@ public class CommunicationManager implements LeavesProtocol {
@ProtocolHandler.PayloadReceiver(payload = SyncmaticaPayload.class)
public static void onPacketGet(ServerPlayer player, SyncmaticaPayload payload) {
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);
}
onPacket(player.connection.exchangeTarget, payload.packetType(), payload.data());
}
public static void onPacket(final @NotNull ExchangeTarget source, final Identifier id, final FriendlyByteBuf packetBuf) {
@@ -331,30 +326,20 @@ 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 = readOrdinal(rotOrdinals, buf.readInt(), "rotation");
final Mirror mir = readOrdinal(mirOrdinals, buf.readInt(), "mirror");
final Rotation rot = rotOrdinals[buf.readInt()];
final Mirror mir = mirOrdinals[buf.readInt()];
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(), readOrdinal(rotOrdinals, buf.readInt(), "sub-region rotation"), readOrdinal(mirOrdinals, buf.readInt(), "sub-region mirror"));
subRegionData.modify(buf.readUtf(32767), buf.readBlockPos(), rotOrdinals[buf.readInt()], mirOrdinals[buf.readInt()]);
}
}
}
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.carpet.config.modules.WoolHopperCounterConfig;
import fun.bm.lophine.config.modules.function.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.hopperCounters && enabled;
return WoolHopperCounterConfig.enabled && enabled;
}
}