Compare commits

...

9 Commits

Author SHA1 Message Date
Helvetica Volubi 132ee404d4 refactor: rename compatibility helper classes for clarity 2026-08-05 00:56:21 +08:00
Helvetica Volubi 0e10a8e8b0 merge patches 2026-08-05 00:49:01 +08:00
Helvetica Volubi 24e68fb203 fix typo 2026-08-05 00:42:33 +08:00
Helvetica Volubi 141c226294 Replace fast compressor with high compressor in buffered linear format 2026-08-05 00:26:22 +08:00
Helvetica Volubi 1049012aff chore: simplify code 2026-08-03 02:25:33 +08:00
Helvetica Volubi 302825cc7e feat: optimize RegionizedTaskQueue TTL and reduce ticket operations in nether portal searching 2026-08-01 16:38:23 +08:00
dependabot[bot] d806e4a423 [ci skip]Bump actions/setup-java from 5 to 5.6.0 (#168)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5 to 5.6.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v5...v5.6.0)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 16:13:12 +08:00
Helvetica Volubi 952c4321d9 fix: fix up BotList 2026-07-31 01:07:56 +08:00
Helvetica Volubi dd7ef6701a feat: update fakeplayer code from Leaves 2026-07-30 02:13:08 +08:00
101 changed files with 1022 additions and 527 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
uses: actions/checkout@v7
- name: Set Up JDK
uses: actions/setup-java@v5
uses: actions/setup-java@v5.6.0
with:
distribution: zulu
java-version: 25
-1
View File
@@ -34,7 +34,6 @@
- morninggloryclip.useMojangSource 强制服务端使用mojang源下载文件
- morninggloryclip.enable.mixin 启用服务器插件的mixin支持
## 📥 下载
### 稳定版本
@@ -5,7 +5,7 @@ Subject: [PATCH] Correct player respawn place
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 57f93d978fe48fdf6e77b7bfb9f1de060e1a8524..924d5f3236d9ba9836f39fc844392099df9cd25c 100644
index 57f93d978fe48fdf6e77b7bfb9f1de060e1a8524..c0e4ddbcf2b1f61fd4a5a6f10882fc1fb4176960 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -511,8 +511,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -43,12 +43,3 @@ index 57f93d978fe48fdf6e77b7bfb9f1de060e1a8524..924d5f3236d9ba9836f39fc844392099
if (inChunk == null) {
continue;
}
@@ -1997,7 +2009,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
if (newLevel.dimension() == lastDimension) {
- this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit
+ this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit // Luminol - Correct player respawn place
this.connection.resetPosition();
transition.postTeleportTransition().onTransition(this);
return this;
@@ -6,7 +6,7 @@ Subject: [PATCH] Do not enable any debug subscriptions
Really this would really crash the server by accident when the operators used F3 + J or toggled the debug synchronizer
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 924d5f3236d9ba9836f39fc844392099df9cd25c..fe34f2e648df9fd1174522baa5913976104b8d04 100644
index c0e4ddbcf2b1f61fd4a5a6f10882fc1fb4176960..4e1346777c0664547f73f8672ed02918392b591f 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -3483,7 +3483,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -6,7 +6,7 @@ Subject: [PATCH] Fix riding statistics desync
Referred to: https://github.com/CraftCanvasMC/Canvas/commit/057175b0c10d5a4d1d9059fd9d077750c32633b2
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index fe34f2e648df9fd1174522baa5913976104b8d04..fee4749c7938779f63155297bf9c7aeb0ca21709 100644
index 4e1346777c0664547f73f8672ed02918392b591f..bc390caff901a3b37a5a4ca3619dd9339fa4cb07 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2516,7 +2516,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix player auto saving ignores interval
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index fee4749c7938779f63155297bf9c7aeb0ca21709..5668906866917f7bb6088ae16146d917d2b840b0 100644
index bc390caff901a3b37a5a4ca3619dd9339fa4cb07..6e39d752aef322fc1cc12bf221cff057cad18578 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -208,7 +208,7 @@ import org.slf4j.Logger;
@@ -275,7 +275,7 @@ index 534f103234eb92571c664cbcfea4ce4e990d3ea8..c4d9d890db784d376b876d70f0468df6
// CraftBukkit start
private final ResourceKey<LevelStem> typeKey;
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 5668906866917f7bb6088ae16146d917d2b840b0..4efbd0f840d74a3d96b28d38e48cba72d5c6fb9b 100644
index 6e39d752aef322fc1cc12bf221cff057cad18578..00dfc496f4e437393f0fc5707f50783418f263f4 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1694,7 +1694,30 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -106,7 +106,7 @@ index 0641b98ef3298eb682ceae83f60b730f3bf90103..cea4bc7036dfd8777c151a0dd811fc13
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 4efbd0f840d74a3d96b28d38e48cba72d5c6fb9b..8e4bbb224d036cf9f33667aec57bbc339c9e8377 100644
index 00dfc496f4e437393f0fc5707f50783418f263f4..f4fb1f36527e7d29b2b4733bbc7309a162d6949d 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -441,7 +441,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -6,7 +6,7 @@ Subject: [PATCH] Add config to enable tick command
only freeze/unfreeze/step/query/rate can run when enabled
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index ff90abb47203c03636d3175f2b3efcf43517b3b0..a2db29aa47a4b7213d4956f02f6e83122ccfdbd1 100644
index ff90abb47203c03636d3175f2b3efcf43517b3b0..a96da8ab0d8ca8241df79fbfca33f3e6072db367 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -239,6 +239,11 @@ public final class RegionizedServer {
@@ -14,7 +14,7 @@ index ff90abb47203c03636d3175f2b3efcf43517b3b0..a2db29aa47a4b7213d4956f02f6e8312
private void globalTick(final long tickCount) {
++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
@@ -41,12 +41,12 @@ index ff90abb47203c03636d3175f2b3efcf43517b3b0..a2db29aa47a4b7213d4956f02f6e8312
private void tickTime(final ServerLevel world, final long tickCount) {
- if (world.tickTime) {
+ 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 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..57a35d7a801621fc461e896eb2bba533d9d5bc1b 100644
index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..ae424c8931a2f82c6c8d4ddd8422a2c142a77a95 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
@@ -92,7 +92,7 @@ index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..57a35d7a801621fc461e896eb2bba533
// 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
@@ -100,7 +100,7 @@ index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..57a35d7a801621fc461e896eb2bba533
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 21f2b9866e1cf36421e10a945fb6fbaa251009ed..aa7931c9b6dc3bba2c8dfecff8df2db302ad905b 100644
index 21f2b9866e1cf36421e10a945fb6fbaa251009ed..409fcc5e95ca453fee7d3bd0375c910d79b507e6 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -259,7 +259,11 @@ public class Commands {
@@ -109,7 +109,7 @@ index 21f2b9866e1cf36421e10a945fb6fbaa251009ed..aa7931c9b6dc3bba2c8dfecff8df2db3
//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 (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
@@ -5,7 +5,7 @@ Subject: [PATCH] Add missing teleportation event APIs for folia
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 8e4bbb224d036cf9f33667aec57bbc339c9e8377..4397f77d0169a3eefd347d3097657de4f6d37ef8 100644
index f4fb1f36527e7d29b2b4733bbc7309a162d6949d..75a36bbd5671992e78fe36a9b3d946ba465919d5 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1803,6 +1803,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config for waypoint restoration
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index aa7931c9b6dc3bba2c8dfecff8df2db302ad905b..c67ea715f02086e5a39cc5832ccdc0b32199db93 100644
index 409fcc5e95ca453fee7d3bd0375c910d79b507e6..5a5f7f7fefacaa0d77ec389d6eb332eff519496a 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -267,7 +267,7 @@ public class Commands {
@@ -8,7 +8,7 @@ As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/4ade1001e4dd19c47d95
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/dimension/end/EnderDragonFight.java b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
index 824ef3f458505569fe5b8efb2055ecea7ba6cc56..3388bf5d2cff00b397af1dd7b9ab93669985b35c 100644
index 824ef3f458505569fe5b8efb2055ecea7ba6cc56..7c68effb78bcb17ca64e043f87d6449f90b1b0a7 100644
--- a/net/minecraft/world/level/dimension/end/EnderDragonFight.java
+++ b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
@@ -317,7 +317,67 @@ public class EnderDragonFight extends SavedData {
@@ -21,7 +21,7 @@ index 824ef3f458505569fe5b8efb2055ecea7ba6cc56..3388bf5d2cff00b397af1dd7b9ab9366
+ 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 - redirect
+ int i, j;
+ for (i = cachePortalChunkIteratorX; i <= 8; ++i) {
+ for (j = cachePortalChunkIteratorZ; j <= 8; ++j) {
@@ -137,7 +137,7 @@ index 2e71a1cbabf3405e3e4fd5349a1784d895e7e60c..42de919064680b1a464d813976ca5e69
if (!itemStack.isEmpty()) {
slots.add(Pair.of(slot, itemStack.copy()));
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 4397f77d0169a3eefd347d3097657de4f6d37ef8..42e09148519596f95fc9c9c63df9c87e6ece3102 100644
index 75a36bbd5671992e78fe36a9b3d946ba465919d5..e029278822f264bd0c66060cd0031a515d43e98f 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1424,7 +1424,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -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 42e09148519596f95fc9c9c63df9c87e6ece3102..444753590d3bc96ce68e25a3834d7abb86e20f94 100644
index e029278822f264bd0c66060cd0031a515d43e98f..0a6c85ff078df07f80faf7cfb39d301d5788584e 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1448,6 +1448,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -5,7 +5,7 @@ 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 a2db29aa47a4b7213d4956f02f6e83122ccfdbd1..6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6 100644
index a96da8ab0d8ca8241df79fbfca33f3e6072db367..f881d10d63a665a73aefe03ba1305ca9ae956513 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -265,6 +265,8 @@ public final class RegionizedServer {
@@ -31,7 +31,7 @@ index 97c514673a454b752ab86b944fd143725ca8090d..ba91d40d6d91588a4b39abfefcb17a36
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index c67ea715f02086e5a39cc5832ccdc0b32199db93..946094713bdb294d7d8beb03967b2a2488f5359b 100644
index 5a5f7f7fefacaa0d77ec389d6eb332eff519496a..f0f6175569100589102d9d76b3ff8f5546030060 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -299,7 +299,11 @@ public class Commands {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 946094713bdb294d7d8beb03967b2a2488f5359b..3d9e8c5ba567efd363e0ed54059f67fbfe25e361 100644
index f0f6175569100589102d9d76b3ff8f5546030060..ddd656e147cdaeb8f91865117e6f9c268b0fd9bc 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -217,7 +217,11 @@ public class Commands {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 3d9e8c5ba567efd363e0ed54059f67fbfe25e361..6642288dde528899d9bce7ccd8d92a199e8975c8 100644
index ddd656e147cdaeb8f91865117e6f9c268b0fd9bc..5fda3083f73744b0df3aab47b3c378dba41b904c 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -246,7 +246,11 @@ public class Commands {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable trigger command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 6642288dde528899d9bce7ccd8d92a199e8975c8..77d7d83cc781baf19593227d20b827bf0be6ed28 100644
index 5fda3083f73744b0df3aab47b3c378dba41b904c..82af03649c7537274aa54ed942e4aae589b97888 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -274,7 +274,11 @@ public class Commands {
@@ -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 444753590d3bc96ce68e25a3834d7abb86e20f94..e64db3045ebf08600283a47960005827c1920f94 100644
index 0a6c85ff078df07f80faf7cfb39d301d5788584e..729fc979fb313ddf2a5c6a04a9a0790440d15830 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -245,6 +245,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -240,7 +240,7 @@ index 3021b70b941ed09c5c58b98d30830a2279b8339c..d289f59475b617ae527d123239297f69
}
}
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..239cad02f85f0d14d4abfa746ecdc4dd82b04657 100644
index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..f70f6501254b40cf76dc7f9bcd621a1f68e39ea9 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -230,6 +230,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -251,16 +251,17 @@ index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..239cad02f85f0d14d4abfa746ecdc4dd
this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings"));
org.spigotmc.SpigotConfig.registerCommands();
@@ -251,6 +252,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
consoleThread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
if (false) this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
+ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info
@@ -254,6 +255,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
+ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info
+
// this.worldData.setGameType(properties.gameMode.get()); // CraftBukkit - moved to world loading
LOGGER.info("Default game type: {}", properties.gameMode.get());
// Paper start - Unix domain socket support
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 5196431f52e81608a5575f8a262cd5c855b06182..6d43ca34f38192faf5bb4254d849c5ac51197f48 100644
index 5196431f52e81608a5575f8a262cd5c855b06182..84c047ed0242778a9e6bca5e41561bd1bdcf633c 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -972,7 +972,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
@@ -272,7 +273,21 @@ index 5196431f52e81608a5575f8a262cd5c855b06182..6d43ca34f38192faf5bb4254d849c5ac
org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
// Paper start - ignore and warn about illegal addEntity calls instead of crashing server
if (!entity.valid || entity.level() != this.level || entity.moonrise$getTrackedEntity() != null) { // Folia - region threading
@@ -1389,6 +1389,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
@@ -1258,6 +1258,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
ServerPlayer player = conn.getPlayer();
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player)) {
this.removePlayer(player);
+ // Leaves start - render bot
+ if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
+ if (bot.needSendFakeData(player)) {
+ bot.sendFakeData(player.connection, false);
+ }
+ }
+ // Leaves end - render bot
}
}
}
@@ -1389,6 +1396,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
}
} else {
this.removePlayer(player);
@@ -344,7 +359,7 @@ index cb11830c2f399c9706b20f8104686dc0d9b686f9..1c4c67410849f844946e4883585910fc
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index e64db3045ebf08600283a47960005827c1920f94..a3d3a602ab86e27ae0c6e6207384dc0043279d47 100644
index 729fc979fb313ddf2a5c6a04a9a0790440d15830..a2e83ca70606a00f36f5b5cbac9f08baf8c5494a 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -232,7 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -564,9 +579,18 @@ index cddf44f5da5cba5603dcff4913b4658dcfcc48db..9eaed81a330a22e7fd6585cd286ec613
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 cb1589e3aa663ca058fb5c3a24da700d4482cf35..d64c68651b7142869a06ce0200fb625cd45ae235 100644
index cb1589e3aa663ca058fb5c3a24da700d4482cf35..1de8eac336e2dd6335c433b7708ce6b6684553c9 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2001,7 +2001,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
return 0; // CraftBukkit
}
- protected void dropExperience(ServerLevel level, @Nullable Entity entity) {
+ public void dropExperience(ServerLevel level, @Nullable Entity entity) {
// CraftBukkit start - Update getExpReward() above if the removed if() changes!
if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
ExperienceOrb.awardWithDirection(level, this.position(), Vec3.ZERO, this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, entity, this); // Paper
@@ -3348,7 +3348,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
private void travelRidden(final Player controller, final Vec3 selfInput) {
Vec3 riddenInput = this.getRiddenInput(controller, selfInput);
@@ -551,7 +551,7 @@ index ed50484ca24ef24b1e5bef9f6369dfa4b30c359c..575b4eabcaac48ae87b69dd037493ebf
// Leaves end - fakeplayer support
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index d64c68651b7142869a06ce0200fb625cd45ae235..1fe317cf3251bff7bb3e0335452a5714d4d31017 100644
index 1de8eac336e2dd6335c433b7708ce6b6684553c9..dae262a073acb3bb3464d169dd5a0b6d67f27846 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -276,7 +276,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -98,7 +98,7 @@ index ae88e57974f631ff2494c35d6e02049ba5d38014..6b8073023833fc9e99684944802dc594
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index a3d3a602ab86e27ae0c6e6207384dc0043279d47..70f7cb6b38a90ca337bd52c18fa7bfd4016b552c 100644
index a2e83ca70606a00f36f5b5cbac9f08baf8c5494a..2c15275066923cb488be8e1d7777785466768332 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1111,6 +1111,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -5,7 +5,7 @@ Subject: [PATCH] Carpet features
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6..7ee9eb8439330724c537f9b1451be78dd3a107ad 100644
index f881d10d63a665a73aefe03ba1305ca9ae956513..7577533f82688304f06c445fd5a1c3fa3c4575fc 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -238,6 +238,7 @@ public final class RegionizedServer {
@@ -15,7 +15,7 @@ index 6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6..7ee9eb8439330724c537f9b1451be78d
+ 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
@@ -280,6 +281,10 @@ public final class RegionizedServer {
}
// Lophine end - Add a config to enable tick command
@@ -28,7 +28,7 @@ index 6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6..7ee9eb8439330724c537f9b1451be78d
this.tickConnections();
diff --git a/net/minecraft/commands/arguments/blocks/BlockInput.java b/net/minecraft/commands/arguments/blocks/BlockInput.java
index 29dcaa5b33e4f6c649b0918721cfaafe9c74eb01..c7e4f2345c8d48b263eeb537d5fcce3ac43bb59e 100644
index 29dcaa5b33e4f6c649b0918721cfaafe9c74eb01..804f7d9d5b71ccff3c16f4c743081c38b658dd3c 100644
--- a/net/minecraft/commands/arguments/blocks/BlockInput.java
+++ b/net/minecraft/commands/arguments/blocks/BlockInput.java
@@ -65,7 +65,11 @@ public class BlockInput implements Predicate<BlockInWorld> {
@@ -37,7 +37,7 @@ index 29dcaa5b33e4f6c649b0918721cfaafe9c74eb01..c7e4f2345c8d48b263eeb537d5fcce3a
public boolean place(final ServerLevel level, final BlockPos pos, final @Block.UpdateFlags int update) {
- BlockState state = (update & Block.UPDATE_KNOWN_SHAPE) != 0 ? this.state : Block.updateFromNeighbourShapes(this.state, level, pos);
+ // Lophine start - Carpet features
+ BlockState state = (update & Block.UPDATE_KNOWN_SHAPE) != 0 || fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates()
+ BlockState state = (update & Block.UPDATE_KNOWN_SHAPE) != 0 || fun.bm.lophine.carpet.InteractionUpdateHelper.shouldSkipUpdates()
+ ? this.state
+ : Block.updateFromNeighbourShapes(this.state, level, pos);
+ // Lophine end - Carpet features
@@ -128,7 +128,7 @@ index 8cc4fe9feb57902a4b9a6a26e6175ac00a2cef65..9ab1a812e43145120859734075e2ac99
// Paper start - fix converting txt to json file; moved from constructor
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 70f7cb6b38a90ca337bd52c18fa7bfd4016b552c..9a6f18fd0eb7e2aef174b25d14cfd0f5a3ade6af 100644
index 2c15275066923cb488be8e1d7777785466768332..9e8157e6a6df32d00fd1f689a6005ce0f7e0dfbd 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -260,6 +260,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -173,7 +173,7 @@ index 70f7cb6b38a90ca337bd52c18fa7bfd4016b552c..9a6f18fd0eb7e2aef174b25d14cfd0f5
public ClientInformation clientInformation() {
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 77b9cd3d14eddc735d9131597916405fde4230ec..b23a47380fb1178696dc49e35d2c3d7dacb4fd1e 100644
index 77b9cd3d14eddc735d9131597916405fde4230ec..52187fe9d2c907e31cf961a93f599231a70ac08c 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2091,7 +2091,15 @@ public class ServerGamePacketListenerImpl
@@ -185,7 +185,7 @@ index 77b9cd3d14eddc735d9131597916405fde4230ec..b23a47380fb1178696dc49e35d2c3d7d
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.interactionUpdates) {
+ this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence());
+ } else {
+ fun.bm.lophine.carpet.InteractionUpdateCompatHelper.runWithSuppressedUpdates(
+ fun.bm.lophine.carpet.InteractionUpdateHelper.runWithSuppressedUpdates(
+ () -> this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence())
+ );
+ }
@@ -226,7 +226,7 @@ index 77b9cd3d14eddc735d9131597916405fde4230ec..b23a47380fb1178696dc49e35d2c3d7d
+ return action.get();
+ }
+
+ return fun.bm.lophine.carpet.InteractionUpdateCompatHelper.supplyWithSuppressedUpdates(action);
+ return fun.bm.lophine.carpet.InteractionUpdateHelper.supplyWithSuppressedUpdates(action);
+ }
+
+ // Lophine end - Carpet features
@@ -238,7 +238,7 @@ index 77b9cd3d14eddc735d9131597916405fde4230ec..b23a47380fb1178696dc49e35d2c3d7d
final String conversationInput = rawMessage;
this.server.processQueue.add(() -> ServerGamePacketListenerImpl.this.getCraftPlayer().acceptConversationInput(conversationInput));
+ // Lophine start - Carpet features
+ } else if (fun.bm.lophine.carpet.CarpetCalculatorCompatHelper.handleChat(this.player, rawMessage)) {
+ } else if (fun.bm.lophine.carpet.CarpetCalculatorHelper.handleChat(this.player, rawMessage)) {
+ return;
+ // Lophine end - Carpet features
} else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check
@@ -424,7 +424,7 @@ index b95c56e0699fbe16e65efcf010cd514f0ac0962f..0125d59551accd9005aa33a5c7cc8ec2
return this.entityData.get(DATA_VALUE);
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 1fe317cf3251bff7bb3e0335452a5714d4d31017..14a79e8ef5a98b1eef2f2d3e0c63f21cb5bb4dbf 100644
index dae262a073acb3bb3464d169dd5a0b6d67f27846..0990e393c8695b17571d9a7646d895ab07ec30ba 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -623,7 +623,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -716,7 +716,7 @@ index 6812ade4d9de26d507234b8357b109ec7e5cbb50..071d2cd7e0c2e5bba0732590ba804a5c
public void addRecipe(RecipeHolder<?> holder) {
org.spigotmc.AsyncCatcher.catchOp("Recipe Add"); // Spigot
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 000e4924e8e338728715a3946002903a3118a98a..55d83a1a97077033191f0f0c220e99095f2a314d 100644
index 000e4924e8e338728715a3946002903a3118a98a..ca92bb3a8b739c0da3f48a2dd16c5fb4fa7e8453 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -1179,7 +1179,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
@@ -725,7 +725,7 @@ index 000e4924e8e338728715a3946002903a3118a98a..55d83a1a97077033191f0f0c220e9909
if (newState == blockState) {
- if (oldState != newState) {
+ // Lophine start - Carpet features
+ boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates();
+ boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateHelper.shouldSkipUpdates();
+ if (skipInteractionUpdates) {
+ updateFlags &= ~Block.UPDATE_NEIGHBORS;
+ }
@@ -744,7 +744,7 @@ index 000e4924e8e338728715a3946002903a3118a98a..55d83a1a97077033191f0f0c220e9909
// CraftBukkit start
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926649b097f 100644
index 0d8d2459457167d78a9a9ea43765980240416947..6da302e1dd755217b82dbc10051324bc8b5d10c1 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -289,6 +289,12 @@ public final class NaturalSpawner {
@@ -753,7 +753,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
double nearestPlayerDistanceSqr = nearestPlayer.distanceToSqr(xx, yStart, zz);
+ // Lophine start - Carpet features
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) {
+ nearestPlayerDistanceSqr = fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.limitDistanceSq(mobCategory, nearestPlayerDistanceSqr);
+ nearestPlayerDistanceSqr = fun.bm.lophine.carpet.LagFreeSpawningHelper.limitDistanceSq(mobCategory, nearestPlayerDistanceSqr);
+ }
+
+ // Lophine end - Carpet features
@@ -766,7 +766,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
if (!mob.isRemoved()) {
+ // Lophine start - Carpet features
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) {
+ fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.markSpawned(level, mob.getType());
+ fun.bm.lophine.carpet.LagFreeSpawningHelper.markSpawned(level, mob.getType());
+ }
+
+ // Lophine end - Carpet features
@@ -780,7 +780,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
- && level.noCollision(type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5));
+ // Lophine start - Carpet features
+ && (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning
+ ? fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.hasNoCollision(level, type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5))
+ ? fun.bm.lophine.carpet.LagFreeSpawningHelper.hasNoCollision(level, type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5))
+ : level.noCollision(type.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5)));
+ // Lophine end - Carpet features
return success ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
@@ -789,7 +789,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
private static @Nullable Mob getMobForSpawn(final ServerLevel level, final EntityType<?> type) {
+ // Lophine start - Carpet features
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) {
+ Mob cachedMob = fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.getOrCreateMob(level, type);
+ Mob cachedMob = fun.bm.lophine.carpet.LagFreeSpawningHelper.getOrCreateMob(level, type);
+ if (cachedMob != null) {
+ return cachedMob;
+ }
@@ -806,7 +806,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
- if (!level.noCollision(spawnerData.type().getSpawnAABB(fx, pos.getY(), fz))
+ // Lophine start - Carpet features
+ if (!(fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning
+ ? fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.hasNoCollision(level.getLevel(), spawnerData.type().getSpawnAABB(fx, pos.getY(), fz))
+ ? fun.bm.lophine.carpet.LagFreeSpawningHelper.hasNoCollision(level.getLevel(), spawnerData.type().getSpawnAABB(fx, pos.getY(), fz))
+ : level.noCollision(spawnerData.type().getSpawnAABB(fx, pos.getY(), fz)))
+ // Lophine end - Carpet features
|| !SpawnPlacements.checkSpawnRules(
@@ -818,7 +818,7 @@ index 0d8d2459457167d78a9a9ea43765980240416947..717cd4b18da2c637fc070c738741f926
level.addFreshEntityWithPassengers(mob, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit
+ // Lophine start - Carpet features
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.lagFreeSpawning) {
+ fun.bm.lophine.carpet.LagFreeSpawningCompatHelper.markSpawned(level.getLevel(), mob.getType());
+ fun.bm.lophine.carpet.LagFreeSpawningHelper.markSpawned(level.getLevel(), mob.getType());
+ }
+ // Lophine end - Carpet features
success = true;
@@ -1182,7 +1182,7 @@ index 972b953a579120c1c05f2dc9bfc2b408d6071d26..a60bb8af6b6aa356193befa9d7e9cdfc
return function != null ? function.evaluate(this.asState(), pos) : Vec3.ZERO;
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index a4d5bf1773a9ce8184a940384696f0d38690a421..cd8ccc6de723bc01390b0439382ea69c775640ba 100644
index a4d5bf1773a9ce8184a940384696f0d38690a421..5b306cc2d4a3cdc3ce08595dc63975c87fca9d3f 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -425,10 +425,10 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -1190,7 +1190,7 @@ index a4d5bf1773a9ce8184a940384696f0d38690a421..cd8ccc6de723bc01390b0439382ea69c
boolean movedByPiston = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0;
boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
- // Leaves start - behaviour 1.21.1-
+ boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateCompatHelper.shouldSkipUpdates(); // Lophine - Carpet features// Leaves start - behaviour 1.21.1-
+ boolean skipInteractionUpdates = fun.bm.lophine.carpet.InteractionUpdateHelper.shouldSkipUpdates(); // Lophine - Carpet features// Leaves start - behaviour 1.21.1-
if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) {
if (blockChanged && oldState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(oldState)) {
- if (!this.level.isClientSide() && sideEffects) {
@@ -1,67 +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 7ee9eb8439330724c537f9b1451be78dd3a107ad..7577533f82688304f06c445fd5a1c3fa3c4575fc 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -241,7 +241,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
@@ -435,7 +435,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 57a35d7a801621fc461e896eb2bba533d9d5bc1b..ae424c8931a2f82c6c8d4ddd8422a2c142a77a95 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 77d7d83cc781baf19593227d20b827bf0be6ed28..82af03649c7537274aa54ed942e4aae589b97888 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/world/level/dimension/end/EnderDragonFight.java b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
index 3388bf5d2cff00b397af1dd7b9ab93669985b35c..e70a6c295e8c26bdf56528826801f037ad0f93b0 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) {
@@ -21,7 +21,7 @@ index dd17339fe2f9d7660b20eed05b61d6231302aa82..d997e4f7ae6ee4e81f5fffe874f2895d
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 9a6f18fd0eb7e2aef174b25d14cfd0f5a3ade6af..b43bbe461500782a75a49c9238bd4d4d81448d09 100644
index 9e8157e6a6df32d00fd1f689a6005ce0f7e0dfbd..2da765eb74c4e84254857ad05b7af82eb8500fc3 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2339,7 +2339,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -34,7 +34,7 @@ index 9a6f18fd0eb7e2aef174b25d14cfd0f5a3ade6af..b43bbe461500782a75a49c9238bd4d4d
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 14a79e8ef5a98b1eef2f2d3e0c63f21cb5bb4dbf..429116ab6bac69054a30b0c766ea5d0186877fae 100644
index 0990e393c8695b17571d9a7646d895ab07ec30ba..386033fa4ba0fb705593e0c9f9cc6574c0ab55ac 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -4004,7 +4004,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -99,7 +99,7 @@ index 6130c477349096d5912dce859b616661e2f43b36..c8c433dcfef3442ff8385c9fc1f1ea47
return true;
} // Paper - Add phantom creative and insomniac controls
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 717cd4b18da2c637fc070c738741f926649b097f..dfb85696affef368d85f93cb0b465abb88267aa1 100644
index 6da302e1dd755217b82dbc10051324bc8b5d10c1..e333abe5bcdd0c571682550d43c7e88d9f6f3296 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -90,7 +90,8 @@ public final class NaturalSpawner {
@@ -5,7 +5,7 @@ Subject: [PATCH] Restore vanilla ender pearl loading
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index b43bbe461500782a75a49c9238bd4d4d81448d09..68e36ad03325cd6348dc4bbab37409b70bee6023 100644
index 2da765eb74c4e84254857ad05b7af82eb8500fc3..d0b9f4140952d0d0416b257077a885d352b40bd1 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -277,7 +277,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -0,0 +1,146 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 1 Aug 2026 16:30:53 +0800
Subject: [PATCH] Anonymous Object: RegionizedTaskQueue queue TTL optimization
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
index fe0a6bd90cba4869a0ee11723832f2dee5039f62..53579b6faa9d55485088d59ec2fd1e4251c2fb01 100644
--- a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
+++ b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicLong;
public final class RegionizedTaskQueue {
private static final TicketType<Long> TASK_QUEUE_TICKET = ChunkSystemTicketType.create("task_queue_ticket", Long::compareTo);
+ private static final long QUEUE_MAX_TTL_TICKS = 5L; // Anonymous - RegionizedTaskQueue queue TTL optimization
public PrioritisedExecutor.PrioritisedTask createChunkTask(final ServerLevel world, final int chunkX, final int chunkZ,
final Runnable run) {
@@ -155,6 +156,58 @@ public final class RegionizedTaskQueue {
}
}
+ // Anonymous start - RegionizedTaskQueue queue TTL optimization
+ public void tickQueueReferenceTTL() {
+ final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> currentRegion
+ = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion();
+ if (currentRegion == null) {
+ return;
+ }
+
+ final ReferenceCountData[] toRemoveTicket = new ReferenceCountData[1];
+
+ for (ConcurrentChainedLong2ReferenceHashTable.TableEntry<ReferenceCountData> counterEntry : this.referenceCounters.entrySet()) {
+ final long coord = counterEntry.getKey();
+ final ReferenceCountData counterData = counterEntry.getValue();
+
+ // only tick for our region
+ if (currentRegion == this.world.regioniser.getRegionAtUnsynchronised(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord))) {
+ long curr = counterData.referenceTTL.get();
+ // successfully decreased ttl
+ if (curr == (curr = counterData.referenceTTL.compareAndExchange(curr, curr - 1))) {
+ if (counterData.referenceCount.get() != 0L) {
+ // still has reference, pump back
+ counterData.referenceTTL.set(QUEUE_MAX_TTL_TICKS);
+ continue;
+ }
+
+ // dead
+ if (curr <= 0) {
+ // parsed from decrementReference
+ this.referenceCounters.computeIfPresent(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> {
+ // might be increased again
+ if (valueInMap.referenceCount.get() != 0L) {
+ valueInMap.referenceTTL.set(QUEUE_MAX_TTL_TICKS); // still has reference, pump back
+ return valueInMap; // directly, the ttl was already charged in add logic
+ }
+
+ // note: valueInMap may not be referenceCountData
+ toRemoveTicket[0] = valueInMap;
+
+ return null;
+ });
+
+ if (toRemoveTicket[0] != null) {
+ this.removeTicket(coord, toRemoveTicket[0].id);
+ toRemoveTicket[0] = null;
+ }
+ }
+ }
+ }
+ }
+ }
+ // Anonymous end - RegionizedTaskQueue queue TTL optimization
+
private void decrementReference(final ReferenceCountData referenceCountData, final long coord) {
if (!referenceCountData.decreaseReferenceCount()) {
return;
@@ -212,9 +265,10 @@ public final class RegionizedTaskQueue {
private final long id = ID_GENERATOR.getAndIncrement();
public final AtomicLong referenceCount = new AtomicLong(1L);
+ public final AtomicLong referenceTTL = new AtomicLong(QUEUE_MAX_TTL_TICKS); // Anonymous - RegionizedTaskQueue queue TTL optimization
public volatile boolean addedTicket;
- // returns false if reference count is 0, otherwise increments ref count
+ // returns false if reference count or ttl is 0, otherwise increments ref count // Anonymous - RegionizedTaskQueue queue TTL optimization
public boolean addCount() {
int failures = 0;
for (long curr = this.referenceCount.get();;) {
@@ -227,6 +281,27 @@ public final class RegionizedTaskQueue {
}
if (curr == (curr = this.referenceCount.compareAndExchange(curr, curr + 1L))) {
+ // Anonymous start - RegionizedTaskQueue queue TTL optimization
+ // now force charge back the ttl to max
+ int ttlFailures = 0;
+ for (long currTTL = this.referenceTTL.get();;) {
+ for (int i = 0; i < ttlFailures; i++) {
+ Thread.onSpinWait();
+ }
+
+ // add failed, rollback (ttl reached)
+ if (currTTL <= 0) {
+ this.referenceCount.decrementAndGet(); // revert the addition
+ return false;
+ }
+
+ if (currTTL == (currTTL = this.referenceTTL.compareAndExchange(currTTL, QUEUE_MAX_TTL_TICKS))) {
+ break;
+ }
+
+ ++ttlFailures;
+ }
+ // Anonymous end - RegionizedTaskQueue queue TTL optimization
return true;
}
@@ -234,11 +309,11 @@ public final class RegionizedTaskQueue {
}
}
- // returns true if new reference count is 0
+ // returns true if new reference count and ttl is 0 // Anonymous - RegionizedTaskQueue queue TTL optimization
public boolean decreaseReferenceCount() {
final long res = this.referenceCount.decrementAndGet();
if (res >= 0L) {
- return res == 0L;
+ return res == 0L && this.referenceTTL.get() <= 0L; // Anonymous - RegionizedTaskQueue queue TTL optimization
} else {
throw new IllegalStateException("Negative reference count");
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 6c5cdfebb3a362c51b3b940397e10536dc67afc8..4a00b2399a190b609f7b0944e407f3b087e617b5 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1756,6 +1756,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PASSENGER_DESYNC_CHECK);
}
// Folia end - fix passenger desync
+ region.world.taskQueueRegionData.tickQueueReferenceTTL(); // Anonymous - RegionizedTaskQueue queue TTL optimization
}
// Folia end - region threading
//this.tickCount++; // Folia - region threading
@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 1 Aug 2026 16:31:57 +0800
Subject: [PATCH] Anonymous Object: Reduce ticket operations in nether portal
searching
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
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 132122f23a697109696852cf383fa1b0186e0210..619521d8ff74c92a822bde9c160931cdfdb7da43 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -221,6 +221,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
private final StructureCheck structureCheck;
public final boolean tickTime; // Folia - region threading
private final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
+ public final io.anonymous.anonymous.utils.ReferenceCountingChunkLoader portalSearchingChunkLoader = new io.anonymous.anonymous.utils.ReferenceCountingChunkLoader(this, net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY); // Anonymous - Reduce ticket operations in nether portal searching
// Luminol start - Level schedulers
private static final java.util.concurrent.atomic.AtomicInteger UNLOADER_ID_GEN = new java.util.concurrent.atomic.AtomicInteger(0);
public final me.earthme.luminol.utils.thread.LevelAwareRegionScheduler levelScheduler = new me.earthme.luminol.utils.thread.LevelAwareRegionScheduler(io.papermc.paper.threadedregions.TickRegions.getScheduler().scheduler);
@@ -1004,6 +1005,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
this.debugSynchronizers.tick(this.server.debugSubscribers());
profiler.pop();
+ this.portalSearchingChunkLoader.tickChunkReferenceTTL(); // Anonymous - Reduce ticket operations in nether portal searching
}
// Folia start - region threading
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 489011f9af49fa3407038bd2f00439443307d179..340e6ad83ba93f3927a08a107e3c8dbafa546112 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -4870,10 +4870,10 @@ public abstract class Entity
);
// kick off search for existing portal or creation
- destination.moonrise$loadChunksAsync(
+ destination.portalSearchingChunkLoader.loadChunksAsync( // Anonymous - Reduce ticket operations in nether portal searching
// add 32 so that the final search for a portal frame doesn't load any chunks
targetPos, portalSearchRadius + 32,
- net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY,
+ //net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY, // Anonymous - Reduce ticket operations in nether portal searching
ca.spottedleaf.concurrentutil.util.Priority.HIGH,
(chunks) -> {
BlockUtil.FoundRectangle portal =
@@ -37,7 +37,7 @@ import java.util.logging.Level;
@SuppressWarnings("unused")
public class KaiijuEntityLimits {
private static final Logger LOGGER = LogUtils.getLogger();
private static final File CONFIG_FOLDER = new File("shiroha_config");
private static final File CONFIG_FOLDER = new File("luminol_config");
protected static final String HEADER =
"Per region entity limits for Kaiiju.\n"
@@ -8,7 +8,7 @@ import net.objecthunter.exp4j.ExpressionBuilder;
import java.math.BigDecimal;
public final class CarpetCalculatorCompatHelper {
public final class CarpetCalculatorHelper {
public static boolean handleChat(ServerPlayer player, String rawMessage) {
if (!GeneralCompatConfig.simpleInGameCalculator || !rawMessage.startsWith("=")) {
@@ -10,8 +10,7 @@ import org.leavesmc.leaves.protocol.CarpetServerProtocol;
import java.util.List;
// WARNING: THIS FILE NEED TO FULLY REWRITTEN
public final class CarpetCompatSync {
public final class CarpetProtocalDataBase {
private static boolean init = false;
public static void apply() {
@@ -24,6 +23,7 @@ public final class CarpetCompatSync {
return configuredLoggers == null ? List.of() : List.copyOf(configuredLoggers);
}
// Rules may be need update because we redirected many config path & the carpet version updated
private static void registerProtocolRules() {
CarpetServerProtocol.CarpetRules.beginBatch();
try {
@@ -2,7 +2,7 @@ package fun.bm.lophine.carpet;
import java.util.function.Supplier;
public final class InteractionUpdateCompatHelper {
public final class InteractionUpdateHelper {
private static final ThreadLocal<Integer> SUPPRESSED_DEPTH = ThreadLocal.withInitial(() -> 0);
public static boolean shouldSkipUpdates() {
@@ -24,7 +24,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public final class LagFreeSpawningCompatHelper {
public final class LagFreeSpawningHelper {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Map<RegionizedWorldData, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
@@ -1,6 +1,6 @@
package fun.bm.lophine.carpet.config.modules;
import fun.bm.lophine.carpet.CarpetCompatSync;
import fun.bm.lophine.carpet.CarpetProtocalDataBase;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
@@ -193,6 +193,6 @@ public class GeneralCompatConfig implements IConfigModule {
@Override
public void beforeFinalLoad() {
// send changes to client
CarpetCompatSync.apply();
CarpetProtocalDataBase.apply();
}
}
@@ -1,8 +1,6 @@
package fun.bm.lophine.config.modules.experiment;
import fun.bm.lophine.enums.GlobalEntitiesCounterType;
import me.earthme.luminol.config.ConfigManager;
import me.earthme.luminol.config.ConfigsInstance;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
@@ -6,9 +6,9 @@ public enum GlobalEntitiesCounterType {
DEFAULT_ASYNC(true, true, true),
PRECISE(true, false, false);
private boolean enabled;
private boolean async;
private boolean defaultModule;
private final boolean enabled;
private final boolean async;
private final boolean defaultModule;
private GlobalEntitiesCounterType(boolean enabled, boolean async, boolean defaultModule) {
this.enabled = enabled;
@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Function;
import java.util.function.Predicate;
public class ConcurrentTable<X, Y, Z> implements AbstractConcurrentTable<X, Y, Z> {
@@ -150,7 +151,7 @@ public class ConcurrentTable<X, Y, Z> implements AbstractConcurrentTable<X, Y, Z
}
private <T> List<T> filterAndCollect(Predicate<TableEntry<X, Y, Z>> filter,
java.util.function.Function<TableEntry<X, Y, Z>, T> mapper) {
Function<TableEntry<X, Y, Z>, T> mapper) {
List<T> result = new ArrayList<>();
for (TableEntry<X, Y, Z> entry : data) {
if (filter.test(entry)) {
@@ -161,8 +162,8 @@ public class ConcurrentTable<X, Y, Z> implements AbstractConcurrentTable<X, Y, Z
}
private <K, V> Map<K, V> filterAndMap(Predicate<TableEntry<X, Y, Z>> filter,
java.util.function.Function<TableEntry<X, Y, Z>, K> keyMapper,
java.util.function.Function<TableEntry<X, Y, Z>, V> valueMapper) {
Function<TableEntry<X, Y, Z>, K> keyMapper,
Function<TableEntry<X, Y, Z>, V> valueMapper) {
Map<K, V> map = new HashMap<>();
for (TableEntry<X, Y, Z> entry : data) {
if (filter.test(entry)) {
@@ -172,7 +173,7 @@ public class ConcurrentTable<X, Y, Z> implements AbstractConcurrentTable<X, Y, Z
return map;
}
private <T> List<T> collectAll(java.util.function.Function<TableEntry<X, Y, Z>, T> mapper) {
private <T> List<T> collectAll(Function<TableEntry<X, Y, Z>, T> mapper) {
List<T> result = new ArrayList<>();
for (TableEntry<X, Y, Z> entry : data) {
result.add(mapper.apply(entry));
@@ -173,7 +173,7 @@ public class OptimizedConcurrentTable<X, Y, Z> extends ConcurrentTable<X, Y, Z>
}
private <K, V, R, S> Map<R, S> buildMapFromIndex(ConcurrentHashMap<K, Set<V>> indexMap, java.util.function.Function<K, R> keyMapper, java.util.function.Function<V, S> valueMapper) {
private <K, V, R, S> Map<R, S> buildMapFromIndex(ConcurrentHashMap<K, Set<V>> indexMap, Function<K, R> keyMapper, Function<V, S> valueMapper) {
Map<R, S> result = new HashMap<>();
if (indexMap != null) {
for (Map.Entry<K, Set<V>> entry : indexMap.entrySet()) {
@@ -81,7 +81,7 @@ public class BufferedLinearRegionFile implements io.anonymous.anonymous.data.Reg
private static final int SECTOR_META_SIZE = Integer.BYTES + Long.BYTES + Integer.BYTES;
// all three are stateless and thread-safe
private static final LZ4Compressor LZ4_COMPRESSOR = LZ4Factory.fastestInstance().fastCompressor();
private static final LZ4Compressor LZ4_COMPRESSOR = LZ4Factory.fastestInstance().highCompressor();
private static final LZ4FastDecompressor LZ4_DECOMPRESSOR = LZ4Factory.fastestInstance().fastDecompressor();
private static final XXHash32 XX_HASH_32 = XXHashFactory.fastestInstance().hash32();
@@ -464,7 +464,8 @@ public class BufferedLinearRegionFile implements io.anonymous.anonymous.data.Reg
// acquired after the region lock is fully released, never inside it (lock hierarchy)
this.masterFileParser.close();
} catch (IOException e) {
if (failure == null) failure = e; else failure.addSuppressed(e);
if (failure == null) failure = e;
else failure.addSuppressed(e);
}
if (failure != null) {
@@ -1,9 +1,9 @@
package io.anonymous.anonymous.enums;
import abomination.LinearRegionFile;
import me.earthme.luminol.config.modules.function.RegionFormatConfig;
import io.anonymous.anonymous.data.BufferedLinearRegionFile;
import io.anonymous.anonymous.utils.RegionFileFactory;
import me.earthme.luminol.config.modules.function.RegionFormatConfig;
import net.minecraft.world.level.chunk.storage.RegionFile;
public enum EnumRegionFormat {
@@ -0,0 +1,312 @@
package io.anonymous.anonymous.utils;
import ca.spottedleaf.concurrentutil.completable.CallbackCompletable;
import ca.spottedleaf.concurrentutil.map.concurrent.longs.ConcurrentChainedLong2ReferenceHashTable;
import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
import io.papermc.paper.threadedregions.RegionizedServer;
import io.papermc.paper.threadedregions.ThreadedRegionizer;
import io.papermc.paper.threadedregions.TickRegions;
import it.unimi.dsi.fastutil.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.jspecify.annotations.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
/**
* 一个简单的基于folia的RegionizedTaskQueue引用计数的轻量ticket区块加载器
* 用于在folia传送门搜索的高频率scheduleChunkLoad的调用下减少ticket操作从而减轻锁负载
* 大部分内容物均取自folia的RegionizedTaskQueue(引用计数), ttl机制取自我的优化
*
* @see io.papermc.paper.threadedregions.RegionizedTaskQueue
* @see Entity#findOrCreatePortalAsync(ServerLevel, BlockPos, ServerLevel, Entity.PortalType, CallbackCompletable)
*/
public class ReferenceCountingChunkLoader {
private static final long MAX_CHUNK_TTL_TICKS = 2L;
private final ServerLevel world;
private final ChunkStatus targetStatus;
private final ConcurrentChainedLong2ReferenceHashTable<ReferenceCountData> referenceCounters = new ConcurrentChainedLong2ReferenceHashTable<>();
public ReferenceCountingChunkLoader(ServerLevel world, ChunkStatus targetStatus) {
this.world = world;
this.targetStatus = targetStatus;
}
private void decrementReference(final @NonNull ReferenceCountData referenceCountData, final long coord) {
if (!referenceCountData.decreaseReferenceCount()) {
return;
}
final ReferenceCountData[] toRemoveTicket = new ReferenceCountData[1];
this.referenceCounters.computeIfPresent(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> {
if (valueInMap.referenceCount.get() != 0L) {
return valueInMap;
}
toRemoveTicket[0] = valueInMap;
return null;
});
if (toRemoveTicket[0] != null) {
this.removeTicket(coord, toRemoveTicket[0].id);
}
}
private void removeTicket(final long coord, final long id) {
this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(
ChunkTaskScheduler.CHUNK_LOAD, coord, ChunkTaskScheduler.getTicketLevel(this.targetStatus), Long.valueOf(id)
);
}
private void addTicket(final long coord, final long id) {
this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel(
ChunkTaskScheduler.CHUNK_LOAD, coord, ChunkTaskScheduler.getTicketLevel(this.targetStatus), Long.valueOf(id)
);
}
private void processTicketUpdates(final long coord) {
this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord));
}
private void ensureTicketAdded(final long coord, final @NonNull ReferenceCountData referenceCountData) {
if (!referenceCountData.addedTicket) {
this.addTicket(coord, referenceCountData.id);
this.processTicketUpdates(coord);
referenceCountData.addedTicket = true;
}
}
public final void loadChunksAsync(final @NonNull BlockPos pos, final int radiusBlocks,
final Priority priority,
final Consumer<List<ChunkAccess>> onLoad) {
this.loadChunksAsync(
(pos.getX() - radiusBlocks) >> 4,
(pos.getX() + radiusBlocks) >> 4,
(pos.getZ() - radiusBlocks) >> 4,
(pos.getZ() + radiusBlocks) >> 4,
priority, onLoad
);
}
public final void loadChunksAsync(final int minChunkX, final int maxChunkX, final int minChunkZ, final int maxChunkZ,
final Priority priority,
final Consumer<List<ChunkAccess>> onLoad) {
this.loadChunksAsync(minChunkX, maxChunkX, minChunkZ, maxChunkZ, priority, onLoad, null);
}
public final void loadChunksAsync(final int minChunkX, final int maxChunkX, final int minChunkZ, final int maxChunkZ,
final Priority priority,
final Consumer<List<ChunkAccess>> onLoad, final Consumer<ChunkAccess> onEachLoad) {
final int requiredChunks = (maxChunkX - minChunkX + 1) * (maxChunkZ - minChunkZ + 1);
final AtomicInteger loadedChunks = new AtomicInteger();
final List<Pair<ReferenceCountData, ChunkAccess>> ret = new ArrayList<>(requiredChunks);
final Consumer<ChunkAccess> consumer = (final ChunkAccess chunk) -> {
if (chunk != null) {
final long pos = chunk.getPos().longKey();
synchronized (ret) {
ret.add(Pair.of(this.incrementReference(pos), chunk));
}
}
if (onEachLoad != null) {
onEachLoad.accept(chunk);
}
if (loadedChunks.incrementAndGet() == requiredChunks) {
try {
if (onLoad != null) {
final List<ChunkAccess> processed = new ArrayList<>(ret.size());
for (Pair<ReferenceCountData, ChunkAccess> result : ret) {
processed.add(result.right());
}
onLoad.accept(processed);
}
} finally {
for (Pair<ReferenceCountData, ChunkAccess> extraRefEntry : ret) {
this.decrementReference(extraRefEntry.left(), extraRefEntry.right().getPos().longKey());
}
}
}
};
for (int cx = minChunkX; cx <= maxChunkX; ++cx) {
for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) {
this.loadAsync(cx, cz, consumer, priority);
}
}
}
public void loadAsync(int chunkX, int chunkZ, Consumer<ChunkAccess> callback, Priority priority) {
final long coord = CoordinateUtils.getChunkKey(chunkX, chunkZ);
final ReferenceCountData increased = this.incrementReference(coord);
final ChunkAccess cached = increased.cached;
if (cached != null) {
RegionizedServer.getInstance().taskQueue.queueChunkTask(this.world, chunkX, chunkZ, () -> {
try {
callback.accept(cached);
} finally {
this.decrementReference(increased, coord);
}
}, priority);
return;
}
this.world.moonrise$getChunkTaskScheduler().scheduleChunkLoad(
chunkX, chunkZ, this.targetStatus, true, priority,
chunk -> {
try {
increased.cached = chunk;
callback.accept(chunk);
} finally {
this.decrementReference(increased, coord);
}
}
);
}
private ReferenceCountData incrementReference(final long coord) {
ReferenceCountData referenceCountData = this.referenceCounters.get(coord);
if (referenceCountData != null && referenceCountData.addCount()) {
this.ensureTicketAdded(coord, referenceCountData);
return referenceCountData;
}
referenceCountData = this.referenceCounters.compute(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> {
if (valueInMap == null) {
return new ReferenceCountData();
}
valueInMap.referenceCount.getAndIncrement();
return valueInMap;
});
this.ensureTicketAdded(coord, referenceCountData);
return referenceCountData;
}
public void tickChunkReferenceTTL() {
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> currentRegion
= io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion();
if (currentRegion == null) {
return;
}
final ReferenceCountData[] toRemoveTicket = new ReferenceCountData[1];
for (ConcurrentChainedLong2ReferenceHashTable.TableEntry<ReferenceCountData> counterEntry : this.referenceCounters.entrySet()) {
final long coord = counterEntry.getKey();
final ReferenceCountData counterData = counterEntry.getValue();
if (currentRegion == this.world.regioniser.getRegionAtUnsynchronised(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord))) {
long curr = counterData.referenceTTL.get();
if (curr == (curr = counterData.referenceTTL.compareAndExchange(curr, curr - 1))) {
if (counterData.referenceCount.get() != 0L) {
counterData.referenceTTL.set(MAX_CHUNK_TTL_TICKS);
continue;
}
if (curr <= 0) {
this.referenceCounters.computeIfPresent(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> {
if (valueInMap.referenceCount.get() != 0L) {
valueInMap.referenceTTL.set(MAX_CHUNK_TTL_TICKS);
return valueInMap;
}
toRemoveTicket[0] = valueInMap;
return null;
});
if (toRemoveTicket[0] != null) {
this.removeTicket(coord, toRemoveTicket[0].id);
toRemoveTicket[0] = null;
}
}
}
}
}
}
private static final class ReferenceCountData {
private static final AtomicLong ID_GENERATOR = new AtomicLong();
private final long id = ID_GENERATOR.getAndIncrement();
public final AtomicLong referenceCount = new AtomicLong(1L);
public final AtomicLong referenceTTL = new AtomicLong(MAX_CHUNK_TTL_TICKS);
public volatile ChunkAccess cached;
public volatile boolean addedTicket;
public boolean addCount() {
int failures = 0;
for (long curr = this.referenceCount.get(); ; ) {
for (int i = 0; i < failures; ++i) {
Thread.onSpinWait();
}
if (curr == 0L) {
return false;
}
if (curr == (curr = this.referenceCount.compareAndExchange(curr, curr + 1L))) {
int ttlFailures = 0;
for (long currTTL = this.referenceTTL.get(); ; ) {
for (int i = 0; i < ttlFailures; i++) {
Thread.onSpinWait();
}
if (currTTL <= 0) {
this.referenceCount.decrementAndGet();
return false;
}
if (currTTL == (currTTL = this.referenceTTL.compareAndExchange(currTTL, MAX_CHUNK_TTL_TICKS))) {
break;
}
++ttlFailures;
}
return true;
}
++failures;
}
}
public boolean decreaseReferenceCount() {
final long res = this.referenceCount.decrementAndGet();
if (res >= 0L) {
return res == 0L && this.referenceTTL.get() <= 0L;
} else {
throw new IllegalStateException("Negative reference count");
}
}
}
}
@@ -2,6 +2,8 @@ package me.earthme.luminol.config.modules.function;
import abomination.LinearRegionFile;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import io.anonymous.anonymous.data.BufferedLinearRegionFileFlusher;
import io.anonymous.anonymous.enums.EnumRegionFormat;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.IllegalFormatConversionExceptionWithOrigin;
import me.earthme.luminol.config.flags.ConfigClassInfo;
@@ -9,8 +11,6 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
import io.anonymous.anonymous.enums.EnumRegionFormat;
import io.anonymous.anonymous.data.BufferedLinearRegionFileFlusher;
import net.minecraft.server.MinecraftServer;
import org.jetbrains.annotations.Nullable;
@@ -96,11 +96,11 @@ public class CheckAndCacheBlockChecker {
}
}
public int getChunkSize(){
public int getChunkSize() {
return this.chunkSections2MaybeContainsMatchingBlock.numChunks;
}
public boolean hasUnloadedPossibleChunks(){
public boolean hasUnloadedPossibleChunks() {
return this.unloadedPossibleChunkSections > 0;
}
@@ -129,14 +129,14 @@ public class CheckAndCacheBlockChecker {
return this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
}
public boolean shouldStop(){
public boolean shouldStop() {
return this.chunkSections2MaybeContainsMatchingBlock.hasNoTrueChunkSections();
}
public boolean checkPosition(BlockPos blockPos) {
if(!this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(blockPos)) return false;
if (!this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(blockPos)) return false;
ChunkAccess chunkAccess = this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
if(chunkAccess == null) {
if (chunkAccess == null) {
if (!this.shouldChunkLoad) {
return false;
}
@@ -35,12 +35,12 @@ public class CommonBlockSearchesCheckAndCache {
public static Optional<BlockPos> blockPosFindClosestMatch(LevelReader levelReader, LivingEntity livingEntity,
int horizontalRange, int verticalRange,
Predicate<BlockState> blockStatePredicate,
boolean shouldChunkLoad){
boolean shouldChunkLoad) {
BlockPos mobPos = livingEntity.blockPosition();
CheckAndCacheBlockChecker checker = new CheckAndCacheBlockChecker(
mobPos, horizontalRange, verticalRange, levelReader, blockStatePredicate, shouldChunkLoad);
checker.initializeChunks();
if(checker.shouldStop()) {
if (checker.shouldStop()) {
return Optional.empty();
}
return BlockPos.findClosestMatch(mobPos, horizontalRange, verticalRange, checker::checkPosition);
@@ -34,7 +34,7 @@ public class NonPOISearchDistances {
return getVanillaSortOrderInt(getRing(dX, dZ), dX, dZ);
}
public static int getRing(final int dX, final int dZ){
public static int getRing(final int dX, final int dZ) {
return Math.max(Math.abs(dX), Math.abs(dZ));
}
@@ -58,8 +58,8 @@ public class NonPOISearchDistances {
* You can convert to longs if you somehow exceed that, but also seriously consider POIs instead.
*
* @param ring Which square ring the block is at relative to the center
* @param dX Relative x position of the block to the center
* @param dZ Relative z position of the block to the center
* @param dX Relative x position of the block to the center
* @param dZ Relative z position of the block to the center
*/
public static int getVanillaSortOrderInt(final int ring, final int dX, final int dZ) {
return (ring << 16 | Math.abs(dX) << 9 | Math.abs(dZ) << 1) - ((dX > 0 ? 1 : 0) << 8 | (dZ > 0 ? 1 : 0));
@@ -25,12 +25,15 @@ public class Pos {
public static int getYSize(LevelHeightAccessor view) {
return view.getHeight();
}
public static int getMinY(LevelHeightAccessor view) {
return view.getMinY();
}
public static int getMaxYInclusive(LevelHeightAccessor view) {
return view.getMaxY();
}
public static int getMaxYExclusive(LevelHeightAccessor view) {
return view.getMaxY() + 1;
}
@@ -39,7 +42,7 @@ public class Pos {
return 15 + getMinInSectionCoord(sectionCoord);
}
public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex){
public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex) {
return getMaxInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex));
}
@@ -66,12 +69,15 @@ public class Pos {
public static int getNumYSections(LevelHeightAccessor view) {
return view.getSectionsCount();
}
public static int getMinYSection(LevelHeightAccessor view) {
return view.getMinSectionY();
}
public static int getMaxYSectionInclusive(LevelHeightAccessor view) {
return view.getMaxSectionY();
}
public static int getMaxYSectionExclusive(LevelHeightAccessor view) {
return view.getMaxSectionY() + 1;
}
@@ -79,6 +85,7 @@ public class Pos {
public static int fromSectionIndex(LevelHeightAccessor view, int sectionCoord) {
return sectionCoord + SectionYCoord.getMinYSection(view);
}
public static int fromBlockCoord(int blockCoord) {
return SectionPos.blockToSectionCoord(blockCoord);
}
@@ -88,12 +95,15 @@ public class Pos {
public static int getNumYSections(LevelHeightAccessor view) {
return view.getSectionsCount();
}
public static int getMinYSectionIndex(LevelHeightAccessor view) {
return 0;
}
public static int getMaxYSectionIndexInclusive(LevelHeightAccessor view) {
return view.getSectionsCount() - 1;
}
public static int getMaxYSectionIndexExclusive(LevelHeightAccessor view) {
return view.getSectionsCount();
}
@@ -102,6 +112,7 @@ public class Pos {
public static int fromSectionCoord(LevelHeightAccessor view, int sectionCoord) {
return sectionCoord - SectionYCoord.getMinYSection(view);
}
public static int fromBlockCoord(LevelHeightAccessor view, int blockCoord) {
return fromSectionCoord(view, SectionPos.blockToSectionCoord(blockCoord));
}
@@ -50,7 +50,7 @@ public class FixedChunkAccessSectionBitBuffer {
this.numSections = yLength * xLength * zLength;
this.chunkSectionBits = new BitSet(numSections);
this.chunkAccesses = new ArrayList<>(Collections.nCopies(xLength * zLength,null));
this.chunkAccesses = new ArrayList<>(Collections.nCopies(xLength * zLength, null));
}
public FixedChunkAccessSectionBitBuffer(BlockPos center, int horizontalRangeInclusive, int verticalRangeInclusive) {
@@ -102,11 +102,11 @@ public class FixedChunkAccessSectionBitBuffer {
return this.getChunkIndex(ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos));
}
public ChunkAccess getChunkAccess(long chunkPos){
public ChunkAccess getChunkAccess(long chunkPos) {
return this.chunkAccesses.get(this.getChunkIndex(chunkPos));
}
public ChunkAccess getChunkAccess(BlockPos blockPos){
public ChunkAccess getChunkAccess(BlockPos blockPos) {
return this.getChunkAccess(ChunkPos.pack(blockPos));
}
@@ -118,14 +118,14 @@ public class FixedChunkAccessSectionBitBuffer {
this.setChunkAccess(ChunkPos.pack(blockPos), chunkAccess);
}
public boolean hasNoTrueChunkSections(){
public boolean hasNoTrueChunkSections() {
return this.chunkSectionBits.nextSetBit(0) == -1;
}
public LongIterable getChunkPosInRange() {
return new LongIterable() {
@Override
public @NotNull LongIterator iterator(){
public @NotNull LongIterator iterator() {
return getChunkPosInRangeIterator();
}
};
@@ -141,7 +141,7 @@ public class FixedChunkAccessSectionBitBuffer {
int z = zMin;
@Override
public long nextLong () {
public long nextLong() {
long result = ChunkPos.pack(x, z);
if (z < zMax) {
z++;
@@ -153,7 +153,7 @@ public class FixedChunkAccessSectionBitBuffer {
}
@Override
public boolean hasNext(){
public boolean hasNext() {
return x <= xMax;
}
};
@@ -162,7 +162,7 @@ public class FixedChunkAccessSectionBitBuffer {
public IntIterable getSectionYInRange() {
return new IntIterable() {
@Override
public @NotNull IntIterator iterator(){
public @NotNull IntIterator iterator() {
return getSectionYInRangeIterator();
}
};
@@ -175,12 +175,12 @@ public class FixedChunkAccessSectionBitBuffer {
int y = yMin;
@Override
public int nextInt(){
public int nextInt() {
return y++;
}
@Override
public boolean hasNext(){
public boolean hasNext() {
return y < yLimit;
}
};
@@ -116,7 +116,7 @@ public record BotCreateState(String rawName, String fullName, String skinName, S
}
public void spawnWithSkin(Consumer<Bot> consumer) {
Bukkit.getAsyncScheduler().runNow(MinecraftInternalPlugin.INSTANCE, (task0) -> {
Bukkit.getAsyncScheduler().runNow(MinecraftInternalPlugin.INSTANCE, (_) -> {
this.mojangAPISkin();
Bukkit.getRegionScheduler().execute(
MinecraftInternalPlugin.INSTANCE,
@@ -22,6 +22,7 @@ import net.minecraft.core.UUIDUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.storage.LevelResource;
@@ -34,7 +35,10 @@ import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class BotDataStorage {
@@ -42,7 +46,7 @@ public class BotDataStorage {
private final File botDir;
private final File botListFile;
private CompoundTag savedBotList;
private final CompoundTag savedBotList;
public BotDataStorage(LevelStorageSource.@NotNull LevelStorageAccess session, String dataDir, String listFileName) {
this.botDir = session.getLevelPath(new LevelResource(dataDir)).toFile();
@@ -52,7 +56,11 @@ public class BotDataStorage {
this.savedBotList = new CompoundTag();
if (this.botListFile.exists() && this.botListFile.isFile()) {
try {
Optional.of(NbtIo.readCompressed(this.botListFile.toPath(), NbtAccounter.unlimitedHeap())).ifPresent(tag -> this.savedBotList = tag);
Optional.of(NbtIo.readCompressed(this.botListFile.toPath(), NbtAccounter.unlimitedHeap())).ifPresent(tag -> {
for (Map.Entry<String, Tag> entry : tag.entrySet()) {
savedBotList.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue());
}
});
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load player data list");
}
@@ -60,7 +68,6 @@ public class BotDataStorage {
}
public void save(Player player) {
boolean flag = true;
try {
CompoundTag nbt = TagUtil.saveEntityWithoutId(player);
File file = new File(this.botDir, player.getStringUUID() + ".dat");
@@ -76,20 +83,19 @@ public class BotDataStorage {
NbtIo.writeCompressed(nbt, file.toPath());
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to save fakeplayer data for {}", player.getScoreboardName(), exception);
flag = false;
return;
}
if (flag && player instanceof ServerBot bot) {
if (player instanceof ServerBot bot) {
CompoundTag nbt = new CompoundTag();
nbt.putString("name", bot.createState.fullName());
nbt.store("uuid", UUIDUtil.CODEC, bot.getUUID());
nbt.putBoolean("resume", bot.resume);
this.savedBotList.put(bot.createState.fullName(), nbt);
this.savedBotList.put(bot.createState.fullName().toLowerCase(Locale.ROOT), nbt);
this.saveBotList();
}
}
public Optional<ValueInput> load(@NotNull ServerBot bot, ProblemReporter reporter) {
return this.load(bot.nameAndId().name(), bot.nameAndId().id().toString()).map(nbt -> {
ValueInput valueInput = TagValueInput.create(reporter, bot.registryAccess(), nbt);
@@ -98,27 +104,27 @@ public class BotDataStorage {
});
}
public void removeSavedData(@NotNull ServerBot bot) {
this.load(bot.nameAndId().name(), bot.nameAndId().id().toString());
public void removeSavedData(String name) {
this.savedBotList.remove(name.toLowerCase(Locale.ROOT));
this.saveBotList();
}
private Optional<CompoundTag> load(String name, String uuid) {
File file = new File(this.botDir, uuid + ".dat");
if (file.exists() && file.isFile()) {
try {
Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
if (!file.delete()) {
throw new IOException("Failed to delete fakeplayer data");
}
this.savedBotList.remove(name);
this.saveBotList();
return optional;
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load fakeplayer data for {}", name);
}
if (!file.exists() || !file.isFile()) {
LOGGER.warn("Failed to load bot {}, the file {} DOES NOT EXIST!", name, file);
return Optional.empty();
}
try {
Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
if (!file.delete()) {
throw new IOException("Failed to delete fakeplayer data");
}
this.removeSavedData(name);
return optional;
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load fakeplayer data for {}", name);
}
return Optional.empty();
}
@@ -153,4 +159,12 @@ public class BotDataStorage {
public CompoundTag getSavedBotList() {
return savedBotList;
}
public UUID getUUIDFromLower(String lowerName) {
return savedBotList.getCompoundOrEmpty(lowerName).read("uuid", UUIDUtil.CODEC).orElseThrow();
}
public String getNameFromLower(String lowerName) {
return savedBotList.getCompoundOrEmpty(lowerName).getString("name").orElseThrow();
}
}
@@ -28,11 +28,11 @@ import fun.bm.lophine.config.modules.function.OldFeatureConfig;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.profile.MutablePropertyMap;
import io.papermc.paper.threadedregions.RegionizedServer;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import io.papermc.paper.util.MCUtil;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.resources.ResourceKey;
@@ -76,7 +76,7 @@ public class BotList {
private final BotDataStorage resumeDataStorage;
private final Map<UUID, ServerBot> botsByUUID = Maps.newHashMap();
private final Map<String, ServerBot> botsByName = Maps.newHashMap();
private final Map<String, ServerBot> botsByLowerName = Maps.newHashMap();
private final Map<String, Set<String>> botsNameByWorldUuid = Maps.newHashMap();
private final Map<String, Set<String>> legacyBotsNameByWorldUuid = Maps.newHashMap();
@@ -141,20 +141,24 @@ public class BotList {
return this.loadNewBot(fullName, this.resumeDataStorage);
}
public ServerBot loadNewBot(String fullName, BotDataStorage storage) {
if (botsByName.containsKey(fullName)) {
public ServerBot loadNewBot(String inputName, BotDataStorage storage) {
String lowerName = inputName.toLowerCase(Locale.ROOT);
if (botsByLowerName.containsKey(lowerName)) {
return null;
}
try {
UUID uuid = BotUtil.getBotUUID(fullName);
BotLoadEvent event = new BotLoadEvent(fullName, uuid);
if (!storage.getSavedBotList().contains(lowerName)) {
return null;
}
String name = storage.getNameFromLower(lowerName);
UUID uuid = storage.getUUIDFromLower(lowerName);
BotLoadEvent event = new BotLoadEvent(name, uuid);
this.server.server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return null;
}
ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, fullName));
ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, name));
bot.connection = new ServerBotPacketListenerImpl(this.server, bot);
Optional<ValueInput> optional;
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(bot.problemPath(), LOGGER)) {
@@ -182,7 +186,7 @@ public class BotList {
ServerLevel world = this.server.getLevel(resourcekey);
return this.placeNewBot(bot, world, bot.getLocation(), nbt);
} catch (Exception e) {
LOGGER.error("Failed to load bot {}", fullName, e);
LOGGER.error("Failed to load bot {}", inputName, e);
return null;
}
}
@@ -213,18 +217,20 @@ public class BotList {
bot.connection.teleport(bot.getX(), bot.getY(), bot.getZ(), bot.getYRot(), bot.getXRot());
this.bots.add(bot);
this.botsByName.put(bot.getScoreboardName().toLowerCase(Locale.ROOT), bot);
this.botsByLowerName.put(bot.getScoreboardName().toLowerCase(Locale.ROOT), bot);
this.botsByUUID.put(bot.getUUID(), bot);
bot.suppressTrackerForLogin = true;
Runnable task = () -> {
world.addNewPlayer(bot);
optional.ifPresent(nbt -> {
bot.loadAndSpawnEnderPearls(nbt);
bot.loadAndSpawnParentVehicle(nbt);
});
world.getCurrentWorldData().connections.add(bot.connection.connection);
world.addNewPlayer(bot);
BotJoinEvent event1 = new BotJoinEvent(bot.getBukkitEntity(), PaperAdventure.asAdventure(Component.translatable("multiplayer.player.joined", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW)));
this.server.server.getPluginManager().callEvent(event1);
@@ -279,13 +285,13 @@ public class BotList {
}
if (bot.removeTaskId != -1) {
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
Bukkit.getGlobalRegionScheduler().cancelTask(bot.removeTaskId);
bot.removeTaskId = -1;
}
bot.disconnect();
this.resumeDataStorage.removeSavedData(bot);
this.resumeDataStorage.removeSavedData(bot.nameAndId().name());
if (event.shouldSave()) {
if (resume) {
this.resumeDataStorage.save(bot);
@@ -293,6 +299,7 @@ public class BotList {
this.manualSaveDataStorage.save(bot);
}
} else {
bot.dropExperience(bot.level(), null);
bot.dropAll(true);
botsNameByWorldUuid.getOrDefault(bot.level().uuid.toString(), new HashSet<>()).remove(bot.getBukkitEntity().getName());
}
@@ -327,7 +334,7 @@ public class BotList {
bot.retireScheduler();
this.bots.remove(bot);
this.botsByName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
this.botsByLowerName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
UUID uuid = bot.getUUID();
ServerBot bot1 = this.botsByUUID.get(uuid);
@@ -400,7 +407,9 @@ public class BotList {
return;
}
CompoundTag savedBotList = this.getResumeBotList().copy();
for (String fullName : savedBotList.keySet()) {
for (Map.Entry<String, Tag> entry : savedBotList.entrySet()) {
String lowerName = entry.getKey();
String fullName = ((CompoundTag) entry.getValue()).getStringOr("name", lowerName);
UUID levelUuid = BotUtil.getBotLevel(fullName, this.resumeDataStorage);
if (levelUuid == null) {
LOGGER.warn("Bot {} has no world UUID, skipping loading.", fullName);
@@ -416,6 +425,7 @@ public class BotList {
private void loadLegacyResumeBotInfo() {
CompoundTag savedBotList = this.getManualSavedBotList().copy();
for (String fullName : savedBotList.keySet()) {
// Legacy format saved fullName as the key
CompoundTag nbt = savedBotList.getCompound(fullName).orElseThrow();
if (!nbt.getBoolean("resume").orElse(false)) {
continue;
@@ -461,7 +471,7 @@ public class BotList {
@Nullable
public ServerBot getBotByName(@NotNull String name) {
return this.botsByName.get(name.toLowerCase(Locale.ROOT));
return this.botsByLowerName.get(name.toLowerCase(Locale.ROOT));
}
public CompoundTag getManualSavedBotList() {
@@ -24,7 +24,6 @@ import net.minecraft.stats.ServerStatsCounter;
import net.minecraft.stats.Stat;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import java.io.File;
@@ -45,7 +44,7 @@ public class BotStatsCounter extends ServerStatsCounter {
}
@Override
public void parse(@NonNull DataFixer fixerUpper, @NonNull JsonElement json) {
public void parse(DataFixer fixerUpper, JsonElement json) {
}
@Override
@@ -18,15 +18,11 @@
package org.leavesmc.leaves.bot;
import com.google.common.base.Charsets;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import net.minecraft.core.NonNullList;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.ItemContainerContents;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
@@ -38,66 +34,23 @@ public class BotUtil {
public static void replenishment(@NotNull ItemStack itemStack, NonNullList<ItemStack> itemStackList) {
int count = itemStack.getMaxStackSize() / 2;
if (itemStack.getCount() <= 8 && count > 8) {
if (pullMatchingStack(itemStack, itemStackList, count)) {
return;
}
if (FakePlayerCompatConfig.fakePlayerAutoReplenishmentFormShulkerBox) {
pullMatchingStackFromShulkerBox(itemStack, itemStackList, count);
}
}
}
private static boolean pullMatchingStack(@NotNull ItemStack targetStack, NonNullList<ItemStack> itemStackList, int transferLimit) {
for (ItemStack inventoryStack : itemStackList) {
if (inventoryStack == ItemStack.EMPTY || inventoryStack == targetStack) {
continue;
}
if (ItemStack.isSameItemSameComponents(inventoryStack, targetStack)) {
if (inventoryStack.getCount() > transferLimit) {
targetStack.setCount(targetStack.getCount() + transferLimit);
inventoryStack.setCount(inventoryStack.getCount() - transferLimit);
} else {
targetStack.setCount(targetStack.getCount() + inventoryStack.getCount());
inventoryStack.setCount(0);
}
return true;
}
}
return false;
}
private static boolean pullMatchingStackFromShulkerBox(@NotNull ItemStack targetStack, NonNullList<ItemStack> itemStackList, int transferLimit) {
for (ItemStack containerStack : itemStackList) {
if (containerStack == ItemStack.EMPTY || !containerStack.is(ItemTags.SHULKER_BOXES)) {
continue;
}
ItemContainerContents contents = containerStack.getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY);
NonNullList<ItemStack> shulkerItems = NonNullList.withSize(contents.items.size(), ItemStack.EMPTY);
contents.copyInto(shulkerItems);
for (int slot = 0; slot < shulkerItems.size(); slot++) {
ItemStack shulkerStack = shulkerItems.get(slot);
if (shulkerStack.isEmpty() || !ItemStack.isSameItemSameComponents(shulkerStack, targetStack)) {
for (ItemStack itemStack1 : itemStackList) {
if (itemStack1 == ItemStack.EMPTY || itemStack1 == itemStack) {
continue;
}
int moved = Math.min(Math.min(transferLimit, shulkerStack.getCount()), targetStack.getMaxStackSize() - targetStack.getCount());
if (moved <= 0) {
return false;
if (ItemStack.isSameItemSameComponents(itemStack1, itemStack)) {
if (itemStack1.getCount() > count) {
itemStack.setCount(itemStack.getCount() + count);
itemStack1.setCount(itemStack1.getCount() - count);
} else {
itemStack.setCount(itemStack.getCount() + itemStack1.getCount());
itemStack1.setCount(0);
}
break;
}
targetStack.grow(moved);
shulkerStack.shrink(moved);
shulkerItems.set(slot, shulkerStack.isEmpty() ? ItemStack.EMPTY : shulkerStack);
containerStack.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(shulkerItems));
return true;
}
}
return false;
}
public static void replaceTool(@NotNull EquipmentSlot slot, @NotNull ServerBot bot) {
@@ -93,7 +93,7 @@ public class ServerBot extends ServerPlayer {
private static final int AUTO_FISH_ENTITY_DELAY = 20;
private final List<AbstractBotAction<?>> actions;
private final Map<String, AbstractBotConfig<?, ?>> configs;
private final Map<String, AbstractBotConfig<?>> configs;
public boolean resume = false;
public BotCreateState createState;
@@ -116,9 +116,10 @@ public class ServerBot extends ServerPlayer {
this.gameMode = new ServerBotGameMode(this);
this.actions = new ArrayList<>();
ImmutableMap.Builder<String, AbstractBotConfig<?, ?>> configBuilder = ImmutableMap.builder();
for (AbstractBotConfig<?, ?> config : Configs.getConfigs()) {
configBuilder.put(config.getName(), config.create().setBot(this));
ImmutableMap.Builder<String, AbstractBotConfig<?>> configBuilder = ImmutableMap.builder();
for (Configs<?> config : Configs.getConfigs()) {
configBuilder.put(config.getName(), config.create(this));
}
this.configs = configBuilder.build();
@@ -147,7 +148,7 @@ public class ServerBot extends ServerPlayer {
this.joining = false;
}
// this.resetOperationCountPerTick(); // Leaves - player operation limiter
//this.resetOperationCountPerTick(); // Leaves - player operation limiter // Lophine
this.wardenSpawnTracker.tick();
if (this.invulnerableTime > 0) {
this.invulnerableTime--;
@@ -303,19 +304,6 @@ public class ServerBot extends ServerPlayer {
this.stopUsingItem();
teleportTransition.postTeleportTransition().onTransition(this);
this.isChangingDimension = false;
// Lophine - We don't have this
/* if (LeavesConfig.modify.netherPortalFix) {
final ResourceKey<Level> fromDim = fromLevel.dimension();
final ResourceKey<Level> toDim = level().dimension();
if (!((fromDim != Level.OVERWORLD || toDim != Level.NETHER) && (fromDim != Level.NETHER || toDim != Level.OVERWORLD))) {
BlockPos fromPortal = org.leavesmc.leaves.util.ReturnPortalManager.findPortalAt(this, fromDim, lastPos);
BlockPos toPos = this.blockPosition();
if (fromPortal != null) {
org.leavesmc.leaves.util.ReturnPortalManager.storeReturnPortal(this, toDim, toPos, fromPortal);
}
}
}*/
if (this.isBlocking()) {
this.stopUsingItem();
}
@@ -348,10 +336,8 @@ public class ServerBot extends ServerPlayer {
ItemStack item = this.getItemInHand(hand);
if (!item.isEmpty()) {
if (FakePlayerCompatConfig.fakePlayerAutoReplenishment) {
BotUtil.replenishment(item, getInventory().getNonEquipmentItems());
}
if (FakePlayerCompatConfig.fakePlayerAutoReplaceTool && BotUtil.isDamage(item, 10)) {
BotUtil.replenishment(item, getInventory().getNonEquipmentItems());
if (BotUtil.isDamage(item, 10)) {
BotUtil.replaceTool(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND, this);
}
}
@@ -421,7 +407,7 @@ public class ServerBot extends ServerPlayer {
if (!this.configs.isEmpty()) {
ValueOutput.TypedOutputList<CompoundTag> configNbt = nbt.list("configs", CompoundTag.CODEC);
for (AbstractBotConfig<?, ?> config : this.configs.values()) {
for (AbstractBotConfig<?> config : this.configs.values()) {
configNbt.add(config.save(new CompoundTag()));
}
}
@@ -432,31 +418,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();
@@ -466,17 +444,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);
Actions<?> holder = Actions.getByName(actionTag.getString("actionName").orElseThrow());
if (holder != null) {
AbstractBotAction<?> newAction = holder.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
});
}
@@ -484,17 +456,12 @@ 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);
String key = configTag.getString("configName").orElseThrow();
if (!this.configs.containsKey(key)) {
LophineLogger.LOGGER.warn("Trying to load a unknown config \"{}\", discard.", key);
continue;
}
this.configs.get(key).load(configTag);
}
}
}
@@ -523,7 +490,7 @@ public class ServerBot extends ServerPlayer {
playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity));
if (login) {
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (task) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (_) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
} else {
playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f)));
}
@@ -573,6 +540,11 @@ public class ServerBot extends ServerPlayer {
getServer().getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false, false);
}
@Override
protected int getBaseExperienceReward(@NotNull ServerLevel level) {
return this.isSpectator() ? 0 : Math.min(this.experienceLevel * 7, 100);
}
@Override
public boolean startRiding(@NotNull Entity vehicle, boolean force, boolean sendGameEvent) {
if (super.startRiding(vehicle, force, sendGameEvent)) {
@@ -764,15 +736,15 @@ public class ServerBot extends ServerPlayer {
}
@SuppressWarnings("unchecked")
public <T, E extends AbstractBotConfig<T, E>> AbstractBotConfig<T, E> getConfig(@NotNull AbstractBotConfig<T, E> config) {
return (AbstractBotConfig<T, E>) Objects.requireNonNull(this.configs.get(config.getName()));
public <T> AbstractBotConfig<T> getConfig(@NotNull Configs<? extends AbstractBotConfig<T>> config) {
return (AbstractBotConfig<T>) Objects.requireNonNull(this.configs.get(config.getName()));
}
public Collection<AbstractBotConfig<?, ?>> getAllConfigs() {
public Collection<AbstractBotConfig<?>> getAllConfigs() {
return configs.values();
}
public <T, E extends AbstractBotConfig<T, E>> T getConfigValue(@NotNull AbstractBotConfig<T, E> config) {
public <T> T getConfigValue(@NotNull Configs<? extends AbstractBotConfig<T>> config) {
return this.getConfig(config).getValue();
}
@@ -81,7 +81,7 @@ public class ServerBotGameMode extends ServerPlayerGameMode {
this.level.sendBlockUpdated(pos, blockState, blockState, 3);
return false;
} else {
BlockState blockState1 = /*isNoBlockUpdate() ? blockState : */block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update
BlockState blockState1 = /*isNoBlockUpdate() ? blockState : */block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update // Lophine
boolean flag = this.level.removeBlock(pos, false);
if (flag) {
block.destroy(this.level, pos, blockState1);
@@ -56,6 +56,11 @@ public class ServerBotPacketListenerImpl extends ServerGamePacketListenerImpl {
public void tick() {
}
@Override
public boolean hasClientLoaded() {
return true; // Don't kick me out!
}
public static class BotConnection extends Connection {
public BotConnection() {
@@ -17,49 +17,54 @@
package org.leavesmc.leaves.bot.agent;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.bot.BotActionGuiContainer;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.agent.actions.*;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.action.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
public class Actions {
public class Actions<T extends AbstractBotAction<T>> {
private static final Map<String, AbstractBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, AbstractBotAction<?>> actionsByClass = new HashMap<>();
private static final Map<String, Actions<? extends AbstractBotAction<?>>> actionsByName = new HashMap<>();
private static final Map<Class<? extends BotAction<?>>, Actions<? extends AbstractBotAction<?>>> actionsByClass = new HashMap<>();
static {
register(new ServerAttackAction(), AttackAction.class);
register(new ServerBreakBlockAction(), BreakBlockAction.class);
register(new ServerDropAction(), DropAction.class);
register(new ServerJumpAction(), JumpAction.class);
register(new ServerSneakAction(), SneakAction.class);
register(new ServerUseItemAutoAction(), UseItemAutoAction.class);
register(new ServerUseItemAction(), UseItemAction.class);
register(new ServerUseItemOnAction(), UseItemOnAction.class);
register(new ServerUseItemToAction(), UseItemToAction.class);
register(new ServerUseItemOffhandAction(), UseItemOffhandAction.class);
register(new ServerUseItemOnOffhandAction(), UseItemOnOffhandAction.class);
register(new ServerUseItemToOffhandAction(), UseItemToOffhandAction.class);
register(new ServerLookAction(), LookAction.class);
register(new ServerFishAction(), FishAction.class);
register(new ServerSwimAction(), SwimAction.class);
register(new ServerRotationAction(), RotationAction.class);
register(new ServerMoveAction(), MoveAction.class);
register(new ServerMountAction(), MountAction.class);
register(new ServerSwapAction(), SwapAction.class);
register(AttackAction.class, ServerAttackAction::new);
register(BreakBlockAction.class, ServerBreakBlockAction::new);
register(DropAction.class, ServerDropAction::new);
register(JumpAction.class, ServerJumpAction::new);
register(SneakAction.class, ServerSneakAction::new);
register(UseItemAutoAction.class, ServerUseItemAutoAction::new);
register(UseItemAction.class, ServerUseItemAction::new);
register(UseItemOnAction.class, ServerUseItemOnAction::new);
register(UseItemToAction.class, ServerUseItemToAction::new);
register(UseItemOffhandAction.class, ServerUseItemOffhandAction::new);
register(UseItemOnOffhandAction.class, ServerUseItemOnOffhandAction::new);
register(UseItemToOffhandAction.class, ServerUseItemToOffhandAction::new);
register(LookAction.class, ServerLookAction::new);
register(FishAction.class, ServerFishAction::new);
register(SwimAction.class, ServerSwimAction::new);
register(RotationAction.class, ServerRotationAction::new);
register(MoveAction.class, ServerMoveAction::new);
register(MountAction.class, ServerMountAction::new);
register(SwapAction.class, ServerSwapAction::new);
}
public static boolean register(@NotNull AbstractBotAction<?> action, Class<?> type) {
public static <T extends AbstractBotAction<T>> boolean register(Class<? extends BotAction<?>> apiType, @NotNull Supplier<T> creator) {
AbstractBotAction<T> action = creator.get();
if (!actionsByName.containsKey(action.getName())) {
actionsByName.put(action.getName(), action);
actionsByClass.put(type, action);
Actions<?> actions = new Actions<>(creator.get().getName(), apiType, creator);
actionsByName.put(action.getName(), actions);
actionsByClass.put(apiType, actions);
if (action.getGuiData() != null) {
BotActionGuiContainer.registerGuiRootNode(action.getGuiData());
}
@@ -68,14 +73,37 @@ public class Actions {
return false;
}
public static boolean register(@NotNull AbstractBotAction<?> action) {
return register(action, action.getClass());
private final String name;
private final Class<?> apiType;
private final Supplier<T> creator;
private Actions(String name, Class<? extends BotAction<?>> apiType, Supplier<T> creator) {
this.name = name;
this.apiType = apiType;
this.creator = creator;
}
public String getName() {
return name;
}
public Class<?> getType() {
return apiType;
}
public T create() {
return creator.get();
}
public T createByCommand(CommandContext context) throws CommandSyntaxException {
T action = create();
action.loadCommand(context);
return action;
}
public static boolean unregister(@NotNull String name) {
AbstractBotAction<?> action = actionsByName.remove(name);
Actions<?> action = actionsByName.remove(name);
BotActionGuiContainer.unregisterGuiRootNode(name);
if (action != null) {
actionsByClass.remove(action.getClass());
return true;
@@ -85,7 +113,7 @@ public class Actions {
@NotNull
@Contract(pure = true)
public static Collection<AbstractBotAction<?>> getAll() {
public static Collection<Actions<? extends AbstractBotAction<?>>> getAll() {
return actionsByName.values();
}
@@ -95,12 +123,12 @@ public class Actions {
}
@Nullable
public static AbstractBotAction<?> getForName(String name) {
public static Actions<?> getByName(String name) {
return actionsByName.get(name);
}
@Nullable
public static AbstractBotAction<?> getForClass(@NotNull Class<?> type) {
public static Actions<?> getByClass(@NotNull Class<?> type) {
return actionsByClass.get(type);
}
}
@@ -19,41 +19,76 @@ package org.leavesmc.leaves.bot.agent;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.configs.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
@SuppressWarnings({"unused"})
public class Configs {
private static final Map<Class<?>, AbstractBotConfig<?, ?>> configs = new HashMap<>();
public class Configs<E extends AbstractBotConfig<?>> {
public static final SkipSleepConfig SKIP_SLEEP = register(new SkipSleepConfig());
public static final AlwaysSendDataConfig ALWAYS_SEND_DATA = register(new AlwaysSendDataConfig());
public static final SpawnPhantomConfig SPAWN_PHANTOM = register(new SpawnPhantomConfig());
public static final SimulationDistanceConfig SIMULATION_DISTANCE = register(new SimulationDistanceConfig());
public static final TickTypeConfig TICK_TYPE = register(new TickTypeConfig());
public static final LocatorBarConfig ENABLE_LOCATOR_BAR = register(new LocatorBarConfig());
private static final Map<String, Configs<? extends AbstractBotConfig<?>>> configs = new HashMap<>();
@Nullable
public static AbstractBotConfig<?, ?> getConfig(String name) {
public static final Configs<SkipSleepConfig> SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new);
public static final Configs<AlwaysSendDataConfig> ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new);
public static final Configs<SpawnPhantomConfig> SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new);
public static final Configs<SimulationDistanceConfig> SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new);
public static final Configs<TickTypeConfig> TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new);
public static final Configs<LocatorBarConfig> ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new);
private final Class<? extends AbstractBotConfig<?>> configClass;
private final Supplier<? extends AbstractBotConfig<?>> configCreator;
private final String name;
private Configs(Class<? extends AbstractBotConfig<?>> configClass, Supplier<? extends AbstractBotConfig<?>> configCreator, String name) {
this.configClass = configClass;
this.configCreator = configCreator;
this.name = name;
}
public String getName() {
return name;
}
@SuppressWarnings("unchecked")
public E create() {
return (E) configCreator.get();
}
@SuppressWarnings("unchecked")
public E create(ServerBot bot) {
E config = (E) configCreator.get();
config.setBot(bot);
return config;
}
@NotNull
public static Optional<Configs<?>> getConfig(String name) {
return configs.values().stream()
.filter(config -> config.getName().equals(name))
.findFirst()
.orElse(null);
.filter(config -> config.name.equals(name))
.findFirst();
}
@NotNull
public static <T> Optional<Configs<?>> getConfig(Class<? extends AbstractBotConfig<T>> configClass) {
return configs.values().stream()
.filter(config -> config.configClass.equals(configClass))
.findFirst();
}
@NotNull
@Contract(pure = true)
public static Collection<AbstractBotConfig<?, ?>> getConfigs() {
public static Collection<Configs<? extends AbstractBotConfig<?>>> getConfigs() {
return configs.values();
}
@SuppressWarnings("unchecked")
private static <T, E extends AbstractBotConfig<T, E>> @NotNull E register(AbstractBotConfig<T, E> instance) {
configs.put(instance.getClass(), instance);
return (E) instance;
private static <T, E extends AbstractBotConfig<T>> @NotNull Configs<E> register(Class<? extends AbstractBotConfig<T>> configClass, Supplier<AbstractBotConfig<T>> configCreator) {
String name = configCreator.get().getName();
Configs<E> config = new Configs<>(configClass, configCreator, name);
configs.put(name, config);
return config;
}
}
@@ -1,3 +1,19 @@
/*
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
*
* Leaves is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Leaves is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
*/
package org.leavesmc.leaves.bot.agent;
import org.apache.commons.lang3.tuple.Pair;
@@ -30,20 +30,19 @@ import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.WrappedArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.event.bot.BotActionExecuteEvent;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.util.UpdateSuppressionException;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
private final String name;
private final Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments;
private final Supplier<E> creator;
private UUID uuid;
private int currentFork = 0;
@@ -61,10 +60,9 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
protected GuiRootNode guiData;
public AbstractBotAction(String name, Supplier<E> creator) {
public AbstractBotAction(String name) {
this.name = name;
this.uuid = UUID.randomUUID();
this.creator = creator;
this.arguments = new HashMap<>();
this.cancel = false;
@@ -75,7 +73,7 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
public abstract boolean doTick(@NotNull ServerBot bot);
public abstract Object asCraft();
public abstract CraftBotAction<?, E> asCraft();
public String getActionDataString() {
return getActionDataString(new ExtraData(new ArrayList<>()));
@@ -201,11 +199,6 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
}
@NotNull
public E create() {
return this.creator.get();
}
public String getName() {
return this.name;
}
@@ -17,11 +17,9 @@
package org.leavesmc.leaves.bot.agent.actions;
import java.util.function.Supplier;
public abstract class AbstractStateBotAction<E extends AbstractStateBotAction<E>> extends AbstractBotAction<E> {
public AbstractStateBotAction(String name, Supplier<E> creator) {
super(name, creator);
public AbstractStateBotAction(String name) {
super(name);
this.setDoNumber(-1);
}
}
@@ -24,15 +24,13 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings;
public abstract class AbstractTimerBotAction<E extends AbstractTimerBotAction<E>> extends AbstractBotAction<E> {
public AbstractTimerBotAction(String name, Supplier<E> creator, GuiRootNode guiData) {
super(name, creator);
public AbstractTimerBotAction(String name, GuiRootNode guiData) {
super(name);
String[] delaySuggestions = {"0", "5", "10", "20"};
String[] intervalSuggestions = {"20", "0", "5", "10"};
this.addArgument("delay", integer(0)).suggests(strings(delaySuggestions)).setOptional(true);
@@ -29,8 +29,6 @@ import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> extends AbstractTimerBotAction<T> {
@@ -38,8 +36,8 @@ public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> ex
private int alreadyUsedTick = 0;
private int useItemRemainingTicks = 0;
public AbstractUseBotAction(String name, Supplier<T> supplier, GuiRootNode guiData) {
super(name, supplier, guiData);
public AbstractUseBotAction(String name, GuiRootNode guiData) {
super(name, guiData);
this.addArgument("use_timeout", integer(-1))
.suggests((context, builder) -> {
builder.suggest("-1", Component.literal("no use timeout"));
@@ -47,7 +45,6 @@ public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> ex
builder.suggest("10", Component.literal("minimum trident shoot time"));
})
.setOptional(true);
if (guiData == null) return;
for (GuiNode node : guiData.getAllFurthestChildren()) {
@@ -23,12 +23,13 @@ import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackAction> {
public ServerAttackAction() {
GuiRootNode guiData = new GuiRootNode("Attack", "Attack an entity", Items.DIAMOND_SWORD, "attack");
super("attack", ServerAttackAction::new, guiData);
super("attack", guiData);
}
@Override
@@ -43,7 +44,7 @@ public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackActio
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerAttackAction> asCraft() {
return new CraftAttackAction(this);
}
}
@@ -30,13 +30,14 @@ import org.bukkit.block.Block;
import org.bukkit.craftbukkit.block.CraftBlock;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction;
public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBlockAction> {
public ServerBreakBlockAction() {
GuiRootNode guiRootNode = new GuiRootNode("Break", "Break a block", Items.DIAMOND_PICKAXE, "break");
super("break", ServerBreakBlockAction::new, guiRootNode);
super("break", guiRootNode);
}
private ItemStack lastItem = null;
@@ -122,7 +123,7 @@ public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBl
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerBreakBlockAction> asCraft() {
return new CraftBreakBlockAction(this);
}
}
@@ -21,13 +21,14 @@ import fun.bm.lophine.bot.action.gui.GuiRootNode;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftDropAction;
public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
public ServerDropAction() {
GuiRootNode guiRootNode = new GuiRootNode("Drop", "Drop all items", Items.BARRIER, "drop");
super("drop", ServerDropAction::new, guiRootNode);
super("drop", guiRootNode);
}
@Override
@@ -37,7 +38,7 @@ public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerDropAction> asCraft() {
return new CraftDropAction(this);
}
}
@@ -26,13 +26,14 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftFishAction;
public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
public ServerFishAction() {
GuiRootNode guiRootNode = new GuiRootNode("Fish", "Fish", Items.FISHING_ROD, "fish");
super("fish", ServerFishAction::new, guiRootNode);
super("fish", guiRootNode);
}
private static final int CATCH_ENTITY_DELAY = 20;
@@ -94,7 +95,7 @@ public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerFishAction> asCraft() {
return new CraftFishAction(this);
}
}
@@ -21,13 +21,14 @@ import fun.bm.lophine.bot.action.gui.GuiRootNode;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction;
public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
public ServerJumpAction() {
GuiRootNode guiRootNode = new GuiRootNode("Jump", "Jump", Items.ELYTRA, "jump");
super("jump", ServerJumpAction::new, guiRootNode);
super("jump", guiRootNode);
}
@Override
@@ -41,7 +42,7 @@ public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerJumpAction> asCraft() {
return new CraftJumpAction(this);
}
}
@@ -31,6 +31,7 @@ import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftLookAction;
public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
@@ -41,7 +42,7 @@ public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
private ServerPlayer target = null;
public ServerLookAction() {
super("look", ServerLookAction::new);
super("look");
this.addArgument("player", ArgumentTypes.player()).setOptional(true);
this.fork(1);
this.addArgument("location", ArgumentTypes.finePosition());
@@ -119,7 +120,7 @@ public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerLookAction> asCraft() {
return new CraftLookAction(this);
}
}
@@ -24,6 +24,7 @@ import org.bukkit.craftbukkit.entity.CraftVehicle;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftMountAction;
import java.util.Comparator;
@@ -32,7 +33,7 @@ import java.util.List;
public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
public ServerMountAction() {
super("mount", ServerMountAction::new);
super("mount");
this.guiData = new GuiRootNode("Mount", "Mount", Items.SADDLE, "mount");
}
@@ -61,7 +62,7 @@ public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerMountAction> asCraft() {
return new CraftMountAction(this);
}
}
@@ -25,6 +25,7 @@ import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.arguments.EnumArgumentType;
import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
@@ -32,7 +33,7 @@ public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
private MoveDirection direction = MoveDirection.FORWARD;
public ServerMoveAction() {
super("move", ServerMoveAction::new);
super("move");
this.addArgument("direction", EnumArgumentType.fromEnum(MoveDirection.class));
this.guiData = new GuiRootNode("Move", "Move", null, "move", false);
@@ -83,7 +84,7 @@ public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerMoveAction> asCraft() {
return new CraftMoveAction(this);
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction;
import java.text.DecimalFormat;
@@ -35,7 +36,7 @@ public class ServerRotationAction extends AbstractBotAction<ServerRotationAction
private static final DecimalFormat DF = new DecimalFormat("0.00");
public ServerRotationAction() {
super("rotation", ServerRotationAction::new);
super("rotation");
this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180))
.suggests((context, builder) -> {
CommandSender sender = context.getSender();
@@ -120,7 +121,7 @@ public class ServerRotationAction extends AbstractBotAction<ServerRotationAction
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerRotationAction> asCraft() {
return new CraftRotationAction(this);
}
}
@@ -20,13 +20,14 @@ package org.leavesmc.leaves.bot.agent.actions;
import fun.bm.lophine.bot.action.gui.GuiRootNode;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction> {
public ServerSneakAction() {
super("sneak", ServerSneakAction::new);
super("sneak");
this.guiData = new GuiRootNode("Sneak", "Sneak", null, "sneak");
}
@@ -48,7 +49,7 @@ public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction>
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSneakAction> asCraft() {
return new CraftSneakAction(this);
}
}
@@ -23,12 +23,13 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction;
public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
public ServerSwapAction() {
super("swap", ServerSwapAction::new);
super("swap");
this.guiData = new GuiRootNode("Swap", "Swap", Items.SHIELD, "swap");
}
@@ -43,7 +44,7 @@ public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSwapAction> asCraft() {
return new CraftSwapAction(this);
}
}
@@ -22,12 +22,13 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction;
public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
public ServerSwimAction() {
super("swim", ServerSwimAction::new);
super("swim");
this.guiData = new GuiRootNode("Swim", "Swim", Items.WATER_BUCKET, "swim");
}
@@ -41,7 +42,7 @@ public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSwimAction> asCraft() {
return new CraftSwimAction(this);
}
}
@@ -21,12 +21,13 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction;
public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemAction> {
public ServerUseItemAction() {
super("use", ServerUseItemAction::new, null);
super("use", null);
}
@Override
@@ -44,7 +45,7 @@ public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemActio
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemAction> asCraft() {
return new CraftUseItemAction(this);
}
}
@@ -30,6 +30,7 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAutoAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
@@ -40,7 +41,7 @@ public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemA
public ServerUseItemAutoAction() {
GuiRootNode guiRootNode = new GuiRootNode("Use", "Use Item", Items.BOW, "use_auto");
super("use_auto", ServerUseItemAutoAction::new, guiRootNode);
super("use_auto", guiRootNode);
}
@Override
@@ -100,7 +101,7 @@ public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemAutoAction> asCraft() {
return new CraftUseItemAutoAction(this);
}
}
@@ -20,6 +20,7 @@ package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.world.InteractionHand;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
@@ -27,7 +28,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseItemOffhandAction> {
public ServerUseItemOffhandAction() {
super("use_offhand", ServerUseItemOffhandAction::new, null);
super("use_offhand", null);
}
@Override
@@ -36,7 +37,7 @@ public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseIt
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOffhandAction> asCraft() {
return new CraftUseItemOffhandAction(this);
}
}
@@ -21,14 +21,16 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction;
public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnAction> {
public ServerUseItemOnAction() {
super("use_on", ServerUseItemOnAction::new, null);
super("use_on", null);
}
@Override
@@ -38,7 +40,7 @@ public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnA
}
public static InteractionResult useItemOn(ServerBot bot, BlockHitResult hitResult, InteractionHand hand) {
if (hitResult == null) {
if (hitResult == null || hitResult.getType() == HitResult.Type.MISS) {
return InteractionResult.FAIL;
}
@@ -57,7 +59,7 @@ public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOnAction> asCraft() {
return new CraftUseItemOnAction(this);
}
}
@@ -21,6 +21,7 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
@@ -28,7 +29,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useIte
public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUseItemOnOffhandAction> {
public ServerUseItemOnOffhandAction() {
super("use_on_offhand", ServerUseItemOnOffhandAction::new, null);
super("use_on_offhand", null);
}
@Override
@@ -38,7 +39,7 @@ public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUse
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOnOffhandAction> asCraft() {
return new CraftUseItemOnOffhandAction(this);
}
}
@@ -27,12 +27,13 @@ import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction;
public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToAction> {
public ServerUseItemToAction() {
super("use_to", ServerUseItemToAction::new, null);
super("use_to", null);
}
@Override
@@ -73,7 +74,7 @@ public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemToAction> asCraft() {
return new CraftUseItemToAction(this);
}
}
@@ -21,6 +21,7 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
@@ -28,7 +29,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useIte
public class ServerUseItemToOffhandAction extends AbstractUseBotAction<ServerUseItemToOffhandAction> {
public ServerUseItemToOffhandAction() {
super("use_to_offhand", ServerUseItemToOffhandAction::new, null);
super("use_to_offhand", null);
}
@Override
@@ -38,7 +39,7 @@ public class ServerUseItemToOffhandAction extends AbstractUseBotAction<ServerUse
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemToOffhandAction> asCraft() {
return new CraftUseItemToOffhandAction(this);
}
}
@@ -32,42 +32,36 @@ import org.leavesmc.leaves.command.WrappedArgument;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.function.Supplier;
public abstract class AbstractBotConfig<T, E extends AbstractBotConfig<T, E>> {
public abstract class AbstractBotConfig<T> {
private final String name;
private final WrappedArgument<T> argument;
private final Supplier<E> creator;
protected ServerBot bot;
public AbstractBotConfig(String name, ArgumentType<T> type, Supplier<E> creator) {
public AbstractBotConfig(String name, ArgumentType<T> type) {
this.name = name;
this.argument = new WrappedArgument<>(name, type);
if (shouldApplySuggestions()) {
this.argument.suggests(this::applySuggestions);
}
this.creator = creator;
}
@SuppressWarnings("RedundantThrows")
public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException {
}
public AbstractBotConfig<T, E> setBot(ServerBot bot) {
public AbstractBotConfig<T> setBot(ServerBot bot) {
this.bot = bot;
return this;
}
public E create() {
return creator.get();
}
public abstract T getValue();
public abstract void setValue(T value) throws CommandSyntaxException;
public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException;
public abstract T parseFromCommand(@NotNull CommandContext context) throws CommandSyntaxException;
public String getName() {
return name;
@@ -23,11 +23,11 @@ import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean, AlwaysSendDataConfig> {
public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public AlwaysSendDataConfig() {
super("always_send_data", BoolArgumentType.bool(), AlwaysSendDataConfig::new);
super("always_send_data", BoolArgumentType.bool());
this.value = FakeplayerConfig.canSendDataAlways;
}
@@ -42,7 +42,7 @@ public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean, AlwaysSendD
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -28,11 +28,11 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfig> {
public class LocatorBarConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public LocatorBarConfig() {
super("enable_locator_bar", BoolArgumentType.bool(), LocatorBarConfig::new);
super("enable_locator_bar", BoolArgumentType.bool());
this.value = FakeplayerConfig.enableLocatorBar && CommandConfig.waypointsAndWaypointCommand;
}
@@ -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
ServerWaypointManager manager = this.bot.level().getWaypointManager();
if (value) {
manager.trackWaypoint(this.bot);
} else {
@@ -65,7 +65,7 @@ public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfi
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -29,10 +29,10 @@ import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import static net.minecraft.network.chat.Component.literal;
public class SimulationDistanceConfig extends AbstractBotConfig<Integer, SimulationDistanceConfig> {
public class SimulationDistanceConfig extends AbstractBotConfig<Integer> {
public SimulationDistanceConfig() {
super("simulation_distance", IntegerArgumentType.integer(2, 32), SimulationDistanceConfig::new);
super("simulation_distance", IntegerArgumentType.integer(2, 32));
}
@Override
@@ -55,7 +55,7 @@ public class SimulationDistanceConfig extends AbstractBotConfig<Integer, Simulat
}
@Override
public Integer loadFromCommand(@NotNull CommandContext context) {
public Integer parseFromCommand(@NotNull CommandContext context) {
return context.getInteger(getName());
}
@@ -26,10 +26,10 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
public class SkipSleepConfig extends AbstractBotConfig<Boolean, SkipSleepConfig> {
public class SkipSleepConfig extends AbstractBotConfig<Boolean> {
public SkipSleepConfig() {
super("skip_sleep", BoolArgumentType.bool(), SkipSleepConfig::new);
super("skip_sleep", BoolArgumentType.bool());
}
@Override
@@ -55,7 +55,7 @@ public class SkipSleepConfig extends AbstractBotConfig<Boolean, SkipSleepConfig>
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -24,11 +24,11 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
public class SpawnPhantomConfig extends AbstractBotConfig<Boolean, SpawnPhantomConfig> {
public class SpawnPhantomConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public SpawnPhantomConfig() {
super("spawn_phantom", BoolArgumentType.bool(), SpawnPhantomConfig::new);
super("spawn_phantom", BoolArgumentType.bool());
this.value = FakeplayerConfig.canSpawnPhantom;
}
@@ -49,7 +49,7 @@ public class SpawnPhantomConfig extends AbstractBotConfig<Boolean, SpawnPhantomC
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -26,16 +26,16 @@ import org.leavesmc.leaves.command.arguments.EnumArgumentType;
import java.util.Locale;
public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType, TickTypeConfig> {
public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType> {
private ServerBot.TickType value;
public TickTypeConfig() {
super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class), TickTypeConfig::new);
super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class));
this.value = FakeplayerConfig.tickType();
}
@Override
public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) {
public ServerBot.TickType parseFromCommand(@NotNull CommandContext context) {
return context.getArgument("tick_type", ServerBot.TickType.class);
}
@@ -64,7 +64,7 @@ public class ConfigCommand extends BotSubcommand {
}
@Contract(pure = true)
private @NotNull Supplier<LiteralNode> configNodeCreator(AbstractBotConfig<?, ?> config) {
private @NotNull Supplier<LiteralNode> configNodeCreator(Configs<? extends AbstractBotConfig<?>> config) {
return () -> new ConfigNode<>(config);
}
@@ -76,13 +76,13 @@ public class ConfigCommand extends BotSubcommand {
protected boolean execute(CommandContext context) {
ServerBot bot = BotArgument.getBot(context);
CommandSender sender = context.getSender();
Collection<AbstractBotConfig<?, ?>> botConfigs = bot.getAllConfigs();
Collection<AbstractBotConfig<?>> botConfigs = bot.getAllConfigs();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
text("configs:", GRAY)
));
for (AbstractBotConfig<?, ?> botConfig : botConfigs) {
for (AbstractBotConfig<?> botConfig : botConfigs) {
sender.sendMessage(join(spaces(),
botConfig.getNameComponent(),
text("=", GRAY),
@@ -94,16 +94,17 @@ public class ConfigCommand extends BotSubcommand {
}
private static class ConfigNode<T> extends LiteralNode {
private final AbstractBotConfig<T, ?> config;
private final Configs<? extends AbstractBotConfig<T>> config;
private ConfigNode(@NotNull AbstractBotConfig<T, ?> config) {
@SuppressWarnings({"rawtypes", "unchecked"})
private ConfigNode(@NotNull Configs config) {
super(config.getName());
this.config = config;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compileBase() {
RequiredArgumentBuilder<CommandSourceStack, ?> argument = config.getArgument()
RequiredArgumentBuilder<CommandSourceStack, ?> argument = config.create().getArgument()
.compile()
.executes(mojangCtx -> {
CommandContext ctx = new CommandContext(mojangCtx);
@@ -115,7 +116,7 @@ public class ConfigCommand extends BotSubcommand {
@Override
protected boolean execute(@NotNull CommandContext context) {
ServerBot bot = BotArgument.getBot(context);
AbstractBotConfig<T, ?> botConfig = bot.getConfig(config);
AbstractBotConfig<?> botConfig = bot.getConfig(config);
context.getSender().sendMessage(join(spaces(),
text("Bot", GRAY),
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
@@ -129,9 +130,9 @@ public class ConfigCommand extends BotSubcommand {
private boolean executeSet(CommandContext context) throws CommandSyntaxException {
ServerBot bot = BotArgument.getBot(context);
AbstractBotConfig<T, ?> botConfig = bot.getConfig(config);
AbstractBotConfig<T> botConfig = bot.getConfig(config);
try {
botConfig.setValue(botConfig.loadFromCommand(context));
botConfig.setValue(botConfig.parseFromCommand(context));
} catch (ClassCastException e) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
}
@@ -24,6 +24,7 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.nbt.CompoundTag;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.BotList;
@@ -32,6 +33,7 @@ import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.bot.BotSubcommand;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -63,7 +65,7 @@ public class LoadCommand extends BotSubcommand {
String botName = context.getArgument(BotNameArgument.class);
BotList botList = BotList.INSTANCE;
CommandSender sender = context.getSender();
if (!botList.getManualSavedBotList().contains(botName)) {
if (!botList.getManualSavedBotList().contains(botName.toLowerCase(Locale.ROOT))) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
}
if (botList.getBotByName(botName) != null) {
@@ -83,13 +85,14 @@ public class LoadCommand extends BotSubcommand {
@Override
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) {
BotList botList = BotList.INSTANCE;
Set<String> bots = botList.getManualSavedBotList().keySet();
CompoundTag list = botList.getManualSavedBotList();
Set<String> bots = list.keySet();
if (bots.isEmpty()) {
return builder
.suggest("<NO SAVED BOT EXISTS>", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first."))
.buildFuture();
}
bots.forEach(builder::suggest);
bots.forEach(key -> builder.suggest(list.getCompoundOrEmpty(key).getString("name").orElseThrow()));
return builder.buildFuture();
}
}
@@ -20,7 +20,6 @@ package org.leavesmc.leaves.command.bot.subcommands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -57,7 +56,7 @@ public class RemoveCommand extends BotSubcommand {
private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender sender, boolean taskQueue) {
if (taskQueue) {
bot.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> removeBotOrigin(bot, sender), null, 1L);
bot.getBukkitEntity().taskScheduler.schedule((LivingEntity _) -> removeBotOrigin(bot, sender), null, 1L);
} else {
return removeBotOrigin(bot, sender);
}
@@ -102,12 +101,12 @@ public class RemoveCommand extends BotSubcommand {
boolean isReschedule = bot.removeTaskId != -1;
if (isReschedule) {
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
}
bot.removeTaskId = ((FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> {
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
bot.removeTaskId = -1;
removeBot(bot, sender);
}, removeTimeSeconds * 20L)).getTaskId();
}, removeTimeSeconds * 20L).getTaskId();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
@@ -52,17 +52,15 @@ public class StartCommand extends LiteralNode {
Actions.getAll().stream().map(this::actionNodeCreator).forEach(this::children);
}
private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction<?> action) throws CommandSyntaxException {
private boolean handleStartCommand(CommandContext context, @NotNull Actions<?> holder) throws CommandSyntaxException {
ServerBot bot = getBot(context);
CommandSender sender = context.getSender();
// Create a new instance of the action to avoid sharing state between multiple actions
AbstractBotAction<?> newAction = action.create();
newAction.loadCommand(context);
if (bot.addBotAction(newAction, sender)) {
AbstractBotAction<?> action = holder.createByCommand(context);
if (bot.addBotAction(action, sender)) {
sender.sendMessage(join(spaces(),
text("Action", GRAY),
text(newAction.getName(), AQUA).hoverEvent(showText(text(newAction.getActionDataString()))),
text(holder.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))),
text("has been issued to", GRAY),
asAdventure(bot.getDisplayName())
));
@@ -72,25 +70,25 @@ public class StartCommand extends LiteralNode {
}
@Contract(pure = true)
private @NotNull Supplier<LiteralNode> actionNodeCreator(AbstractBotAction<?> action) {
private @NotNull Supplier<LiteralNode> actionNodeCreator(Actions<?> action) {
return () -> new ActionLiteralNode(action);
}
private class ActionLiteralNode extends LiteralNode {
private final AbstractBotAction<?> action;
private final Actions<?> holder;
private ActionLiteralNode(@NotNull AbstractBotAction<?> action) {
super(action.getName());
this.action = action;
private ActionLiteralNode(@NotNull Actions<?> holder) {
super(holder.getName());
this.holder = holder;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
ArgumentBuilder<CommandSourceStack, ?> builder = super.compile();
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = action.getArguments();
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = holder.create().getArguments();
Command<CommandSourceStack> executor = context -> {
if (handleStartCommand(new CommandContext(context), action)) {
if (handleStartCommand(new CommandContext(context), holder)) {
return Command.SINGLE_SUCCESS;
} else {
return 0;
@@ -70,7 +70,7 @@ public class CraftBot extends CraftPlayer implements Bot {
@Override
public BotAction<?> getAction(int index) {
return (BotAction<?>) this.getHandle().getBotActions().get(index).asCraft();
return this.getHandle().getBotActions().get(index).asCraft();
}
@Override

Some files were not shown because too many files have changed in this diff Show More