Compare commits

...

55 Commits

Author SHA1 Message Date
Helvetica Volubi ac3653dda7 [ci skip]Update Gradle wrapper to version 9.2.0 2025-11-12 00:56:44 +08:00
Helvetica Volubi a08fd04751 Update Luminol to fix a sentry bug 2025-11-12 00:20:46 +08:00
Helvetica Volubi f5debe9ee1 [ci skip] Update Luminol 2025-11-10 17:27:08 +08:00
Helvetica Volubi 1a84d2e670 Update Luminol to fix a crash bug in config command system 2025-11-10 00:27:08 +08:00
Helvetica Volubi e96891275d [ci skip] update datapack command save 2025-11-09 02:38:51 +08:00
Helvetica Volubi 9e342c6683 Update Luminol 2025-11-06 00:12:13 +08:00
Helvetica Volubi 00f7f5ee2b fix: fixes #69 2025-11-01 02:53:48 +08:00
Helvetica Volubi 77b9582c4a Update Luminol 2025-10-31 22:23:17 +08:00
Helvetica Volubi 184048fd26 Update Luminol 2025-10-31 00:23:24 +08:00
Helvetica Volubi 7ccca03023 try to fix BBOR protocol 2025-10-29 02:09:22 +08:00
Helvetica Volubi b34fa8237e feat: provided void trade instead of infinite trade
fixes #77
2025-10-29 00:20:45 +08:00
Helvetica Volubi 42a4d18717 refactor: deprecated tickCount 2025-10-27 21:40:42 +08:00
Helvetica Volubi 2d8d7f5784 refactor: prepare to drop reuse tickCount 2025-10-27 21:11:51 +08:00
Helvetica Volubi bf509bcded feat: wool hopper counter(#27) 2025-10-27 19:59:03 +08:00
Helvetica Volubi ef6759a9ab [ci skip] Update Luminol to skip release by robot 2025-10-27 05:40:37 +00:00
Helvetica Volubi bc1483ea7a fix: try to fix Concurrent throw in protocol 2025-10-27 00:10:44 +08:00
Helvetica Volubi 5768a60ba8 fix: rewrite request block data method 2025-10-25 03:22:14 +08:00
Helvetica Volubi 05434f422c fix: fixes #63 2025-10-23 00:20:15 +08:00
Helvetica Volubi 21e9299352 Update code from Leaves 2025-10-22 11:34:52 +08:00
Helvetica Volubi 83e7718346 fix: try fix #63 2025-10-22 02:41:51 +08:00
Helvetica Volubi 5845b976c1 fix: try fix #70 2025-10-22 02:15:15 +08:00
xiaoxijun 4ca94280ae Add support for more mod protocols (#73)
* Add Syncmatica protocols

* Add AppleSkin protocols

* Add BBOR Protocol

* Add Jade Protocol

* Add Xaero Map Protocol

* Add Support REI protocol

* Fixed an issue where the configuration file was not loading correctly.

* move config file directory

* add license & refactor code

* update leaves fix

https://github.com/LeavesMC/Leaves/issues/747#event-19986621829

* Update Luminol

* fix up jade protocol

* fix up rei

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com>
2025-10-20 00:06:40 +08:00
Helvetica Volubi 4cc49c6d99 fix: fix bot save command 2025-10-20 00:02:21 +08:00
Helvetica Volubi 93c0258c7e fix: use local lastTickCount to save data 2025-10-19 23:40:17 +08:00
Helvetica Volubi 43a5ea0385 Update Luminol 2025-10-18 02:34:13 +08:00
Helvetica Volubi 678882a435 Update Luminol & fix a bug in shutdown server 2025-10-14 19:14:12 +08:00
Helvetica Volubi 8e5884147f fix: fix async bugs
fixes #70
2025-10-12 11:54:30 +08:00
Helvetica Volubi b999cf9f5f [ci skip] update ci 2025-10-11 23:34:49 +08:00
Helvetica Volubi 847bcd54e0 Update Luminol 2025-10-06 14:20:14 +08:00
Helvetica Volubi 15a55403ff Modify merge ItemEntity logic
Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius, when the merge radius is large and stacks containing many items get stuck in an unexpected position, individual items may never reach their destination. This configuration option is added to fix this behavior.
2025-10-04 01:15:49 +08:00
Helvetica Volubi 482809df6e [ci skip]fix: fix default translations support 2025-10-03 18:24:30 +08:00
Helvetica Volubi 5db8ec4bd9 fix: pre fix a bug in I18n (will cause bug in 1.21.9) 2025-10-03 17:03:37 +08:00
Helvetica Volubi d60cd46c15 Update Luminol 2025-10-02 16:51:47 +08:00
Helvetica Volubi df40d4bdc9 Update Luminol 2025-10-01 23:21:57 +08:00
Helvetica Volubi 0084883933 feat: add config to enable scoreboard command unsafe 2025-09-29 22:59:44 +08:00
Helvetica Volubi 1d1e4ec70b fix: fixes #62 2025-09-29 16:49:58 +08:00
Helvetica Volubi 1927a66d8e fix:fix a bug in config of multi-format 2025-09-29 00:14:55 +08:00
Helvetica Volubi 38442749e7 fix: fixes #65 2025-09-28 17:39:20 +08:00
Helvetica Volubi 70dae5976d fix: try fixes #63 2025-09-28 15:49:30 +08:00
Helvetica Volubi b08756b4b3 fix: fixes #64 2025-09-28 14:44:04 +08:00
Helvetica Volubi 5e658adad3 Update Luminol 2025-09-28 13:12:54 +08:00
Bacteriawa 4d6e08312a Update Luminol 2025-09-25 23:43:14 +08:00
Helvetica Volubi 9efe6499d0 Update Luminol 2025-09-24 01:08:36 +08:00
Helvetica Volubi 319946e8c1 fixes #61 2025-09-21 21:14:01 +08:00
Helvetica Volubi 28ce6ae7b1 Update Luminol & fix up CI 2025-09-19 15:10:55 +08:00
Helvetica Volubi af4a8a8731 Update Luminol 2025-09-13 22:17:35 +08:00
Helvetica Volubi 7059c6a062 Update Luminol & Leaves Redstone Shears Wrench 2025-09-13 04:03:53 +08:00
Helvetica Volubi 98a8b65665 Update Luminol 2025-09-13 02:39:56 +08:00
Helvetica Volubi ac6b1e2377 Update Luminol 2025-09-12 05:09:04 +08:00
Helvetica Volubi 0e964ae71c fixes #58 2025-09-11 17:24:13 +08:00
Helvetica Volubi ba6bd9f71c Update Luminol 2025-09-06 17:15:36 +08:00
Helvetica Volubi 4513cfd637 Fake Player command use brigadier (#57)
* pre update for new command system branch

* update ref
2025-09-05 03:30:27 +08:00
Helvetica Volubi d87cca6a97 fix: fix shutdown problem if bot was not removed in world 2025-09-04 21:38:52 +08:00
Helvetica Volubi 79dbac2a8e Update Luminol 2025-09-04 17:30:46 +08:00
Helvetica Volubi 4d3e3ac832 feat: add function command unsafe support 2025-09-04 02:19:09 +08:00
237 changed files with 13262 additions and 1753 deletions
+78 -10
View File
@@ -7,6 +7,20 @@ on:
pull_request:
branches:
- "**"
workflow_dispatch:
inputs:
force-release:
description: "Force disable release if you enter 2, force release if you enter 1, default release if not released else skip release"
required: false
default: ""
force-push:
description: "Force disable push to repo if you enter 2, push to repo if you enter 1, default push if not released else skip push repo"
required: false
default: ""
comments:
description: "Add comments to release"
required: false
default: ""
permissions: write-all
@@ -18,14 +32,14 @@ jobs:
- name: Checkout Git Repository
uses: actions/checkout@v5
- name: Set up JDK
- name: Set Up JDK
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v5
- name: Grant execute permission for gradlew
run: chmod +x gradlew
@@ -36,36 +50,90 @@ jobs:
- name: Apply All Patches
run: ./gradlew --refresh-dependencies applyAllPatches
- name: CreateMojmapPaperclipJar
- name: Build Paperclip Jar
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
- name: Upload Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ env.project_id_b }} CI Artifacts
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
- name: SetENV
- name: Set Environment
if: github.event_name != 'pull_request'
run: sh scripts/SetENV.sh
- name: Publish to repo
if: github.event_name != 'pull_request' && env.flag_release == 'true' && false # do not push to any repo
- name: Check If Release Exists
if: github.event_name != 'pull_request' && env.flag_release == 'true'
run: |
git fetch --tags
if [ -n "$(git tag -l "${{ env.tag }}")" ]; then
echo "Release already exists"
release_exists=true
else
echo "Release does not exist"
release_exists=false
fi
if [ "$release_exists" == "true" ]; then
counter=1
while [ -n "$(git tag -l "${{ env.tag }}-${counter}")" ]; do
counter=$((counter + 1))
done
echo "tag=${{ env.tag }}-${counter}" >> $GITHUB_ENV
echo "release_count= - ${counter}" >> $GITHUB_ENV
fi
echo "release_exists=${release_exists}" >> $GITHUB_ENV
- name: Publish To Repo
if: (( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-push == '2')) || inputs.force-push == '1') && false # do not push to any repo
continue-on-error: true
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
env:
PRIVATE_MAVEN_REPO_PASSWORD: ${{ secrets.PRIVATE_MAVEN_REPO_PASSWORD }}
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
- name: Create Release
if: github.event_name != 'pull_request' && env.flag_release == 'true'
- name: Create Release - Pre Process
if: ( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
run: |
if [ ${{ inputs.comments }} == "" ]; then
echo "No comments provided"
echo "flag_comment=true" >> $GITHUB_ENV
else
echo "flag_comment=false" >> $GITHUB_ENV
fi
- name: Create Release - No Comment
if: env.flag_comment == 'false'
uses: ncipollo/release-action@v1
with:
tag: ${{ env.tag }}
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}${{ env.release_count }}
body: |
📦Version: `${{ env.mcversion }}` | Commit ${{ env.commit_id }} [![download](https://img.shields.io/github/downloads/LuminolMC/${{ env.project_id }}/${{ env.tag }}/total?color=red&style=flat-square)](https://github.com/LuminolMC/${{ env.project_id }}/releases/download/${{ env.tag }}/${{ env.jar }})
This release is automatically compiled by GitHub Actions
### Branch Info
> ${{ github.ref_name }}
### Commit Message
${{ env.commit_msg }}
artifacts: ${{ env.jar_dir }}
generateReleaseNotes: true
prerelease: ${{ env.pre }}
makeLatest: ${{ env.make_latest }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release - With Comment
if: env.flag_comment == 'true'
uses: ncipollo/release-action@v1
with:
tag: ${{ env.tag }}
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}${{ env.release_count }}
body: |
📦Version: `${{ env.mcversion }}` | Commit ${{ env.commit_id }} [![download](https://img.shields.io/github/downloads/LuminolMC/${{ env.project_id }}/${{ env.tag }}/total?color=red&style=flat-square)](https://github.com/LuminolMC/${{ env.project_id }}/releases/download/${{ env.tag }}/${{ env.jar }})
This release is automatically compiled by GitHub Actions
### Comments
> ${{ inputs.comments }}
### Branch Info
> ${{ github.ref_name }}
### Commit Message
${{ env.commit_msg }}
artifacts: ${{ env.jar_dir }}
+1 -1
View File
@@ -4,7 +4,7 @@ mcVersion=1.21.8
release=2
# 0 for skip release, 1 for pre-release, 2 for release
luminolRef=fa4e778f2ab92b0ccef57fad830660766b3f2f18
luminolRef=a3c596e26bfdf197a1c0c7a536c8a2bf7f97c09d
org.gradle.configuration-cache=true
org.gradle.caching=true
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+2 -2
View File
@@ -51,7 +51,7 @@
// Luminol start - Dependenices insert
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
implementation("com.github.luben:zstd-jni:1.5.4-1")
@@ -276,14 +_,14 @@
@@ -275,14 +_,14 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
@@ -70,7 +70,7 @@
"Build-Number" to (build ?: ""),
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
@@ -447,7 +_,7 @@
@@ -446,7 +_,7 @@
}
fill {
@@ -5,27 +5,27 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 4be82092886728b7862b6e8951cf1c8ab917ca55..1b822e9576573c360b997e5cb4fa02278c88b74f 100644
index d8066afd5f3f2ea9a5dff87d853562e22268785c..f8b2364fa162a41304a99a4993354e33528ab801 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -21,6 +21,7 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of(new File("luminol_config"), "luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", ConfigsInstance.of(new File("lophine_config"), "lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
preLoad();
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
index f164e41975adee8b68dbcb400007681c0b66a4f8..4e76fb3b1274f2fde734089b20458f6561c39700 100644
index df5d926fb4401dd93d658fe14ae4d9d58cff68f9..b6d84fea596cfa78032151ab2f206b6b3d5dd197 100644
--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
@@ -8,7 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "server_mod_name")
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "server_mod_name")
public class ServerModNameConfig implements IConfigModule {
@ConfigInfo(baseName = "name")
@ConfigInfo(name = "name")
- public static String serverModName = "Luminol";
+ public static String serverModName = "Lophine";
@ConfigInfo(baseName = "vanilla_spoof")
@ConfigInfo(name = "vanilla_spoof")
public static boolean fakeVanilla = false;
@@ -5,26 +5,26 @@ Subject: [PATCH] Transformed Configs
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
index 4e906e8e0ebd57b9f7000e4194280e3e3636e52c..14eefd162c9facd54a53718a7a0b1b0266e1ada8 100644
index 4051384e82dba0416838c3c9889a6e368367b601..a5535b479cdcca870d0c8be6ed6fbcb32f266ac2 100644
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
@@ -11,6 +11,7 @@ public class CommandConfig implements IConfigModule {
@TransformedConfig(name = "enable", category = {"experiment", "force_the_data_command_to_be_enabled"})
@ConfigInfo(baseName = "enable_data_command")
@TransformedConfig(name = "enable", directory = {"experiment", "force_the_data_command_to_be_enabled"})
@ConfigInfo(name = "enable_data_command")
public static boolean data = false;
+ @TransformedConfig(name = "command_block_enabled", category = {"experiment", "command"}, originInstance = "lophine")
@TransformedConfig(name = "enabled", category = {"experiment", "force_enable_command_block_command_execution"})
@ConfigInfo(baseName = "enable_command_block")
public static boolean commandBlock = false;
+ @TransformedConfig(name = "command_block_enabled", directory = {"experiment", "command"}, originInstance = "lophine")
@TransformedConfig(name = "enabled", directory = {"experiment", "force_enable_command_block_command_execution"})
@ConfigInfo(name = "enable_command_block", comments = """
Force to enable command blocks.
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
index 192a67360db810934d02a15c955af3579e6f6b20..fbafc5a8aa2581301e62e12adb22169ab7fd8e19 100644
index 35e6014f04093050a9a62b895b43e5c5d8c6a28e..11abfb884f972fd73ca4c13a6e309de1bcd23fd5 100644
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
@@ -8,6 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.OPTIMIZATIONS, mainName = "force_disable_packet_limiter_of_paper")
@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "force_disable_packet_limiter_of_paper")
public class PaperPacketLimiterConfig implements IConfigModule {
+ @TransformedConfig(name = "unlimit-packet", category = {"misc", "network"}, originInstance = "lophine")
@TransformedConfig(name = "force_disable", category = {"misc", "force_disable_packet_limiter_of_paper"})
@ConfigInfo(baseName = "force_disable")
+ @TransformedConfig(name = "unlimit-packet", directory = {"misc", "network"}, originInstance = "lophine")
@TransformedConfig(name = "force_disable", directory = {"misc", "force_disable_packet_limiter_of_paper"})
@ConfigInfo(name = "force_disable")
public static boolean forceDisable = false;
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/d93e9766d3797d130
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
index 102de78be0eb82d6898b4104fad1bf5e8366f993..0f8c9d4932c8bbd619f21d4aa28b890e14439b46 100644
index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981c4e34aed 100644
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
@@ -17,12 +17,173 @@
@@ -185,4 +185,3 @@ index 102de78be0eb82d6898b4104fad1bf5e8366f993..0f8c9d4932c8bbd619f21d4aa28b890e
+ }
+ }
}
\ No newline at end of file
@@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 16:30:54 +0800
Subject: [PATCH] Add config to allow infinite trade
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
index 79242037e868a140513f032e74e8594c0c6ff41c..050e89c3e95c7c3ef7ad98f8ef03ab206241a7e2 100644
--- a/net/minecraft/world/entity/npc/Villager.java
+++ b/net/minecraft/world/entity/npc/Villager.java
@@ -490,8 +490,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
private void resendOffersToTradingPlayer() {
- MerchantOffers offers = this.getOffers();
+ // Lophine start - infinite trade
+ MerchantOffers offers = this.getOffers().copy();
Player tradingPlayer = this.getTradingPlayer();
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
+ for (MerchantOffer merchantOffer : offers) {
+ merchantOffer.maxUses = 524288;
+ }
+ }
+ // Lophine end - infinite trade
if (tradingPlayer != null && !offers.isEmpty()) {
tradingPlayer.sendMerchantOffers(
tradingPlayer.containerMenu.containerId,
diff --git a/net/minecraft/world/item/trading/Merchant.java b/net/minecraft/world/item/trading/Merchant.java
index 6e2fa442ddcd4ef3c4fe789b9ebac9dd409c9de7..0c7318a0ed214204f5493576c8a7b02fbe51c00b 100644
--- a/net/minecraft/world/item/trading/Merchant.java
+++ b/net/minecraft/world/item/trading/Merchant.java
@@ -42,7 +42,14 @@ public interface Merchant {
new SimpleMenuProvider((containerId, inventory, player1) -> new MerchantMenu(containerId, inventory, this), displayName)
);
if (optionalInt.isPresent()) {
- MerchantOffers offers = this.getOffers();
+ // Lophine start - infinite trade
+ MerchantOffers offers = this.getOffers().copy();
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
+ for (MerchantOffer merchantOffer : offers) {
+ merchantOffer.maxUses = 5242884;
+ }
+ }
+ // Lophine end - infinite trade
if (!offers.isEmpty()) {
player.sendMerchantOffers(optionalInt.getAsInt(), offers, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock());
}
diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java
index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..770f37d7158c7b4cec62783025f623a68c1f2457 100644
--- a/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/net/minecraft/world/item/trading/MerchantOffer.java
@@ -196,7 +196,7 @@ public class MerchantOffer {
}
public boolean isOutOfStock() {
- return this.uses >= this.maxUses;
+ return (this.uses >= this.maxUses && !fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade); // Lophine - infinite trade
}
public void setToOutOfStock() {
@@ -48,7 +48,7 @@ index 11e6197dec541b28733715f0d7eaa4c7b834d632..de1263404395c28209234a556347284f
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 567d63ae589705e13403814b36e35d00c241a69e..3f4b1c54f9207ba1854a8c8da965cbaca5ea517d 100644
index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc01846eaf7 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1948,6 +1948,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -18,7 +18,7 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 8ec753fe9c84ffe1188f7e7ebb6895cf4bba9e39..ee4a459700d75676eae3422d4a0e10be73c45871 100644
index f5539ca5964abb18124522a8aa7ce940517b2011..1258591aae1b926ee8085b1984d553b8d3a1df7e 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
@@ -30,7 +30,7 @@ index 8ec753fe9c84ffe1188f7e7ebb6895cf4bba9e39..ee4a459700d75676eae3422d4a0e10be
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
@@ -6472,4 +6472,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -6482,4 +6482,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 2 Jul 2025 23:36:25 +0800
Subject: [PATCH] Add config to enable datapack command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index e05f75b6bbd48d6fb7379926d68d5f8ed6014be9..af895859057ca303177ec3c8a07cf7534e62cca6 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -192,7 +192,9 @@ public class Commands {
if(me.earthme.luminol.config.modules.experiment.CommandConfig.data) {
DataCommands.register(this.dispatcher); // Folia - region threading - TODO
}
- //DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.datapack) {
+ DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ }
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
DefaultGameModeCommands.register(this.dispatcher);
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 100e8fdc52c201d386e3c779d19f6b5abde39820..d08a5b553f4e5932d960fbcdeb6a43419730e32a 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2352,6 +2352,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
}
+ // Lophine start - region thread skip reload // TODO - add reload support
+ public void saveDatapacks(Collection<String> selectedIds) {
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
+ );
+ this.worldData.setDataConfiguration(worldDataConfiguration);
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
+
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
// Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
index b540a3c3a02f7242578a63477e34b9063e86f1d2..9f0adf157872e1c68cd7752a24eacdc636e8d17a 100644
--- a/net/minecraft/server/commands/ReloadCommand.java
+++ b/net/minecraft/server/commands/ReloadCommand.java
@@ -16,6 +16,12 @@ public class ReloadCommand {
private static final Logger LOGGER = LogUtils.getLogger();
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
+ // Lophine start - region thread skip reload // TODO - add reload support
+ if (true) {
+ source.getServer().saveDatapacks(selectedIds);
+ return;
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Thu, 4 Sep 2025 02:14:16 +0800
Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 11697e65a7f7871920ca7bad37de07f78a3da1f8..25ccbfa12d57d540195ecc16aa54a144f8ecc0e8 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -204,7 +204,9 @@ public class Commands {
FillCommand.register(this.dispatcher, context);
FillBiomeCommand.register(this.dispatcher, context);
ForceLoadCommand.register(this.dispatcher);
- //FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.function) {
+ FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ }
GameModeCommand.register(this.dispatcher);
GameRuleCommand.register(this.dispatcher, context);
GiveCommand.register(this.dispatcher, context);
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 29 Sep 2025 22:56:03 +0800
Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 25ccbfa12d57d540195ecc16aa54a144f8ecc0e8..22d211bee83e3ef34d6ac81dd89c0e73924bee90 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -229,7 +229,11 @@ public class Commands {
//RotateCommand.register(this.dispatcher); // Folia - region threading - TODO later
SayCommand.register(this.dispatcher);
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
- //ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
+ // Lophine start - Add a config to enable scoreboard command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.scoreboard) {
+ ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
+ }
+ // Lophine start - Add a config to enable scoreboard command
SeedCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
VersionCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
SetBlockCommand.register(this.dispatcher, context);
@@ -97,10 +97,10 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
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 af895859057ca303177ec3c8a07cf7534e62cca6..94a3cea5d42b1f98bbde22ef514f8f7dbd64ba58 100644
index 22d211bee83e3ef34d6ac81dd89c0e73924bee90..1fb359073342a657e9e493403263b56be5b3393f 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -245,7 +245,11 @@ public class Commands {
@@ -249,7 +249,11 @@ public class Commands {
TeleportCommand.register(this.dispatcher);
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
@@ -114,7 +114,7 @@ index af895859057ca303177ec3c8a07cf7534e62cca6..94a3cea5d42b1f98bbde22ef514f8f7d
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d08a5b553f4e5932d960fbcdeb6a43419730e32a..a0f1db50adf5163a671d3d9e9df7adb7de4250c6 100644
index 75027e73859c955a54034640f905cb5d91a6a2f4..2f4970242c754cfba8ff5656a63af07d9d0a723c 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1,20 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 18:19:00 +0800
Subject: [PATCH] Add config to enable unsafe waypoint bar
Subject: [PATCH] Add config to enable waypoint command & bar
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 94a3cea5d42b1f98bbde22ef514f8f7dbd64ba58..e311977fca4d0ba6e3efd4a41b2732cf5e7b4b9c 100644
index 1fb359073342a657e9e493403263b56be5b3393f..451a685782da46f5683ea6707289bbaf3193771f 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -253,7 +253,11 @@ public class Commands {
@@ -257,7 +257,11 @@ public class Commands {
TimeCommand.register(this.dispatcher);
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ // Lophine start - unsafe waypoint bar
+ if (fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) {
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ }
+ // Lophine end - unsafe waypoint bar
@@ -22,7 +22,7 @@ index 94a3cea5d42b1f98bbde22ef514f8f7dbd64ba58..e311977fca4d0ba6e3efd4a41b2732cf
WorldBorderCommand.register(this.dispatcher);
if (JvmProfiler.INSTANCE.isAvailable()) {
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e9905c1b2 100644
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254b9b656d7 100644
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
@@ -22,7 +22,14 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
@@ -31,7 +31,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e
public void trackWaypoint(WaypointTransmitter waypoint) {
- // Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.waypoints.add(waypoint);
+
+ for (ServerPlayer serverPlayer : this.players) {
@@ -46,7 +46,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e
public void addPlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.players.add(player);
+
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
@@ -62,7 +62,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e
public void updatePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.row(player);
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
+
@@ -79,7 +79,7 @@ index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e
public void removePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.connections.row(player).values().removeIf(connection -> {
+ connection.disconnect();
+ return true;
@@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 2 Jul 2025 23:36:25 +0800
Subject: [PATCH] Fix datapack command save function
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 2f4970242c754cfba8ff5656a63af07d9d0a723c..b156b5c635f931a3d4abc0584591f90476d011a6 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2353,6 +2353,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
}
+ // Lophine start - region thread skip reload // TODO - add reload support
+ public void saveDatapacks(Collection<String> selectedIds) {
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
+ );
+ this.worldData.setDataConfiguration(worldDataConfiguration);
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
+
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
// Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
index a5032b34752061d61fd9ddb4db828d35e403f5e7..3eaa9c85d06f6ecc8ed639d8befa861439390eb7 100644
--- a/net/minecraft/server/commands/DataPackCommand.java
+++ b/net/minecraft/server/commands/DataPackCommand.java
@@ -98,7 +98,7 @@ public class DataPackCommand {
dispatcher.register(
Commands.literal("datapack")
.requires(Commands.hasPermission(2))
- /*.then( // Luminol - Add back read-only datapack command
+ .then(
Commands.literal("enable")
.then(
Commands.argument("name", StringArgumentType.string())
@@ -160,11 +160,11 @@ public class DataPackCommand {
.suggests(SELECTED_PACKS)
.executes(commandContext -> disablePack(commandContext.getSource(), getPack(commandContext, "name", false)))
)
- )*/ // Luminol - Add back read-only datapack command
+ )
.then(
Commands.literal("list")
.executes(commandContext -> listPacks(commandContext.getSource()))
- // .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource()))) // Luminol - Add back read-only datapack command
+ .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource())))
.then(Commands.literal("enabled").executes(commandContext -> listEnabledPacks(commandContext.getSource())))
)
.then(
@@ -252,7 +252,7 @@ public class DataPackCommand {
}
private static int listPacks(CommandSourceStack source) {
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
+ return listEnabledPacks(source) + listAvailablePacks(source);
}
private static int listAvailablePacks(CommandSourceStack source) {
@@ -280,7 +280,7 @@ public class DataPackCommand {
private static int listEnabledPacks(CommandSourceStack source) {
PackRepository packRepository = source.getServer().getPackRepository();
- // packRepository.reload(); // Luminol - Add back read-only datapack command
+ packRepository.reload();
Collection<? extends Pack> selectedPacks = packRepository.getSelectedPacks();
if (selectedPacks.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.datapack.list.enabled.none"), false);
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
index b540a3c3a02f7242578a63477e34b9063e86f1d2..bc999de32931558d0d8dc26264653dd63c1cad19 100644
--- a/net/minecraft/server/commands/ReloadCommand.java
+++ b/net/minecraft/server/commands/ReloadCommand.java
@@ -16,11 +16,17 @@ public class ReloadCommand {
private static final Logger LOGGER = LogUtils.getLogger();
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
+ // Lophine start - region thread skip reload // TODO - add reload support
+ source.getServer().saveDatapacks(selectedIds);
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
+ if (false) {
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
return null;
});
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
}
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
@@ -8,27 +8,18 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 8405157ec35a443e238fa6866772c839621d73d7..4edb6e6e6287f232f7eef45c747554264ec05319 100644
index 8405157ec35a443e238fa6866772c839621d73d7..67f3454e6479abb241a7d94699d4f7bec22da56b 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -334,6 +334,8 @@ public final class RegionizedServer {
}
// Luminol end - Add a config to enable tick command
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(tickCount); // Leaves - protocol
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(); // Leaves - protocol
+
// tick connections
this.tickConnections();
@@ -443,6 +445,8 @@ public final class RegionizedServer {
world.updateTickData();
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
+
world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); // required to eventually process ticket updates
}
diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644
--- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
@@ -57,36 +48,6 @@ index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f93
}
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index a0f1db50adf5163a671d3d9e9df7adb7de4250c6..af13707933af14171447d5ab6faacb64ddf194a7 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - regionised ticking
public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer();
+ private int tickCount;
@Override
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
@@ -2226,9 +2227,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false;
}
+ // Lophine start - reuse tick count
public int getTickCount() {
- throw new UnsupportedOperationException(); // Folia - region threading
+ if (false) throw new UnsupportedOperationException(); // Folia - region threading
+ return this.tickCount;
+ }
+
+ public void handleTickCount(int tickCount1) {
+ tickCount = tickCount1;
}
+ // Lophine end - reuse tick count
public int getSpawnProtectionRadius() {
return 16;
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3ddc776bf9e 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 29 Oct 2025 00:09:09 +0800
Subject: [PATCH] Leaves: Configurable trading with the void
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 985ddea9d74a37f58f32a27375f6f7e6af0f2192..9796c449f924b8fd9c0dd6bb02cf196641e495ed 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2901,7 +2901,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Spigot start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start - Fix merchant inventory not closing on entity removal
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Leaves - Configurable trading with the void
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
}
// Paper end - Fix merchant inventory not closing on entity removal
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..6c1f4f943a5be5f2e43a82cca52ca76a98226915 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -649,7 +649,7 @@ public abstract class PlayerList {
player.stopRiding();
rootVehicle.getPassengersAndSelf().forEach(entity -> {
// Paper start - Fix villager boat exploit
- if (entity instanceof net.minecraft.world.entity.npc.AbstractVillager villager) {
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity instanceof net.minecraft.world.entity.npc.AbstractVillager villager) { // Leaves - Configurable trading with the void
final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer();
if (human != null) {
villager.setTradingPlayer(null);
diff --git a/net/minecraft/world/inventory/MerchantMenu.java b/net/minecraft/world/inventory/MerchantMenu.java
index d59f67ffe34201c63e3d9706a4434f33b6732edb..c635c7211bff9d190b7035b284dda162334fd5c2 100644
--- a/net/minecraft/world/inventory/MerchantMenu.java
+++ b/net/minecraft/world/inventory/MerchantMenu.java
@@ -74,6 +74,7 @@ public class MerchantMenu extends AbstractContainerMenu {
@Override
public boolean stillValid(Player player) {
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade) return this.trader.getTradingPlayer() == player; // Leaves - Configurable trading with the void
if (!checkReachable) return true; // Paper - checkReachable
return this.trader.stillValid(player);
}
@@ -446,10 +446,10 @@ index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b
}
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index accbf3256db42b1ce15ea022fcfe1c61e8cb1c7a..8b7d885ae0ec48039dc1573a5227c322454e46ab 100644
index 699bb3cc2b680a4ee438a88c05854e5ab05ea910..d4fe03fd766caca1d7693a5317460ca1a9b9fa4f 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -145,7 +145,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -148,7 +148,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public void setItem(int index, ItemStack stack) {
this.unpackLootTable(null);
this.getItems().set(index, stack);
@@ -458,7 +458,7 @@ index accbf3256db42b1ce15ea022fcfe1c61e8cb1c7a..8b7d885ae0ec48039dc1573a5227c322
}
@Override
@@ -759,9 +759,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -743,9 +743,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (item.isEmpty()) {
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
@@ -7,25 +7,6 @@ Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/79d9ef74c2684eb49060f07e1ab31c827326c9a5/leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 6db566adf2d0df1d26221eda04aa01738df6d3d2..24ebfdf98e343a7892af621d032c35819156deec 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -56,6 +56,14 @@ public class BlockItem extends Item {
if (blockPlaceContext == null) {
return InteractionResult.FAIL;
} else {
+ // Leaves start - shears wrench
+ if (org.leavesmc.leaves.util.ShearsWrenchUtil.shouldSkipPlace(context)) {
+ if (context.getPlayer() != null) {
+ context.getPlayer().containerMenu.forceHeldSlot(blockPlaceContext.getHand());
+ }
+ return InteractionResult.FAIL;
+ }
+ // Leaves end - shears wrench
BlockState placementState = this.getPlacementState(blockPlaceContext);
// CraftBukkit start - special case for handling block placement with water lilies and snow buckets
org.bukkit.block.BlockState bukkitState = null;
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
index 8cf3e51e12f9cf98836657e722edb23943f9e866..5fd5e9fd4e1a79dd1a9d62a5cf0c308805979420 100644
--- a/net/minecraft/world/item/ShearsItem.java
@@ -6,7 +6,7 @@ Subject: [PATCH] Compatibility fix for Raid Revert and Cross Region Damage
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 3f4b1c54f9207ba1854a8c8da965cbaca5ea517d..a8348a073682eec31990e9ab963b11ad32cf8bf8 100644
index e94687b3aa960f9c630f459fedc17bc01846eaf7..f4f4f886b6558d39d292a45665953f497f84be53 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1216,6 +1216,29 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -5,10 +5,18 @@ Subject: [PATCH] I18n support
diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java
index 7b9e2a1a208b46a69c16e6afd8b502259893574f..db46a31ea8a36562e548eb07f0c4cf9b9e8c3360 100644
index 7b9e2a1a208b46a69c16e6afd8b502259893574f..c300ae4363298fecef8fa9bf739f01c0a11e145f 100644
--- a/net/minecraft/locale/Language.java
+++ b/net/minecraft/locale/Language.java
@@ -65,7 +65,7 @@ public abstract class Language {
@@ -36,6 +36,7 @@ public abstract class Language {
Map<String, String> map = new HashMap<>();
BiConsumer<String, String> biConsumer = map::put;
parseTranslations(biConsumer, "/assets/minecraft/lang/en_us.json");
+ fun.bm.lophine.utils.ServerI18nUtil.loadLophineI18nDefault(biConsumer);
deprecatedTranslationsInfo.applyToMap(map);
final Map<String, String> map1 = Map.copyOf(map);
return new Language() {
@@ -65,7 +66,7 @@ public abstract class Language {
};
}
@@ -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 6b7c92fdf562dfa46eee8e8acbc82b02fc3226c5..c29e9c6cb2513fe4b01a619e16433893efb44e6f 100644
index de1263404395c28209234a556347284fa557f81c..44f0e3a675c612e9ca2bc40cc3898bdbca0f6718 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -232,6 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 30 Aug 2025 17:16:32 +0800
Subject: [PATCH] Leaves: Leaves Fakeplayer
Subject: [PATCH] Leaves: Fakeplayer
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
@@ -33,10 +33,10 @@ index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4
private DisconnectionDetails disconnectionDetails;
private boolean encrypted;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index af13707933af14171447d5ab6faacb64ddf194a7..e5e3a9c6443019d31496b1cf2154f5c3eaf6f972 100644
index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786e46148b1 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -348,6 +348,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -347,6 +347,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Folia end - regionised ticking
@@ -45,15 +45,19 @@ index af13707933af14171447d5ab6faacb64ddf194a7..e5e3a9c6443019d31496b1cf2154f5c3
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
AtomicReference<S> atomicReference = new AtomicReference<>();
@@ -1066,6 +1068,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1038,6 +1040,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia end - region threading
LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
+ this.getBotList().removeAll(); // Leaves - save or remove bot
// CraftBukkit start
if (this.server != null) {
if (false) this.server.spark.disable(); // Paper - spark // Luminol - Force disable builtin spark
@@ -1588,7 +1591,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void stopServer() {
+ // Leaves end - save or remove bot
+ if (!this.getBotList().forceShutdown && !this.getBotList().removeAll()) {
+ return;
+ }
+ // Leaves end - save or remove bot
// Folia start - region threading
// halt scheduler
// don't wait, we may be on a scheduler thread
@@ -1588,7 +1595,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = this.pauseWhileEmptySeconds() * 20;
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
@@ -62,7 +66,7 @@ index af13707933af14171447d5ab6faacb64ddf194a7..e5e3a9c6443019d31496b1cf2154f5c3
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1912,6 +1915,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1912,6 +1919,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void tickConnection() {
this.getConnection().tick();
@@ -70,7 +74,7 @@ index af13707933af14171447d5ab6faacb64ddf194a7..e5e3a9c6443019d31496b1cf2154f5c3
}
private void synchronizeTime(ServerLevel level) {
@@ -2990,6 +2994,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2983,6 +2991,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return 0;
}
@@ -215,7 +219,7 @@ index f2286b96b8f40b4588f817913c42ae7b4a92340f..e6c7bbb023000b9de90c1256274ff5ab
playerList.op(gameProfile);
i++;
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f604b0d6890 100644
index 0e278f7b9ed85ce8c3cedd9154f817b30ff1e48a..09d4b1d68c3f046ef304016a1afe7a3038dfae3e 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -162,6 +162,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -262,7 +266,7 @@ index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348f
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6cf992049 100644
index 4f1976c47a087bf4f36687124ef29ca7b664f682..96aafe4d63446b3d212f21f14091858f72bb081f 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -207,6 +207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -294,7 +298,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
@Override
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
Optional<Holder<PoiType>> optional = PoiTypes.forState(oldState);
@@ -2826,6 +2834,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2827,6 +2835,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
@@ -306,7 +310,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
if (serverPlayer.isReceivingWaypoints()) {
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
}
@@ -2913,6 +2926,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2914,6 +2927,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
@@ -319,7 +323,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index c29e9c6cb2513fe4b01a619e16433893efb44e6f..ff803b5f73f7d2cfe9351add12c3fde69a1642b1 100644
index 44f0e3a675c612e9ca2bc40cc3898bdbca0f6718..4b2dba8b30b72fb3acc00957b3e19d6fc178c99e 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -219,7 +219,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -430,7 +434,7 @@ index 144a2644c15f276f02bb3be859dc5d05a677ac55..c6a89e8936cffa49b3de153ed3c40e3c
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74af2697442 100644
index 8e2775e873c92beed6a0e4e8ce1304ab8ca6e8d1..580f114fd99b017403c61e994d0c947d00e5115d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -425,6 +425,19 @@ public abstract class PlayerList {
@@ -441,7 +445,7 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false);
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, true);
+ }
+ this.server.getBotList().bots.forEach(bot1 -> {
+ bot1.sendPlayerInfo(player);
@@ -516,35 +520,35 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
public boolean canBypassPlayerLimit(GameProfile profile) {
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
index 36e9b027ce5213f8914728293633e78e9905c1b2..a8c2a93cc12bd5aa6760bed91baa680f3801ee5e 100644
index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd13444f4ad 100644
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
@@ -22,6 +22,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
@Override
@@ -24,6 +24,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
public void trackWaypoint(WaypointTransmitter waypoint) {
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ // Leaves start - fakeplayer
+ if (waypoint instanceof org.leavesmc.leaves.bot.ServerBot bot && !bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.ENABLE_LOCATOR_BAR)) {
+ return;
+ }
+ // Leaves end - fakeplayer
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
this.waypoints.add(waypoint);
@@ -57,6 +62,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
public void addPlayer(ServerPlayer player) {
for (ServerPlayer serverPlayer : this.players) {
@@ -59,6 +64,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
// Folia - region threading
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
this.players.add(player);
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index ee4a459700d75676eae3422d4a0e10be73c45871..16c323ead67a9a4ef48d25670b89297a15457849 100644
index 1258591aae1b926ee8085b1984d553b8d3a1df7e..365cb2aed3d0f428ba33d4debdf3c3a3c494882d 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -566,7 +570,7 @@ index ee4a459700d75676eae3422d4a0e10be73c45871..16c323ead67a9a4ef48d25670b89297a
final boolean yZero = movement.y == 0.0;
final boolean zZero = movement.z == 0.0;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index a8348a073682eec31990e9ab963b11ad32cf8bf8..8ce6f3f1a931628e018ce9a2e0c404b8c8a4d992 100644
index f4f4f886b6558d39d292a45665953f497f84be53..12466e0294123a5922ee7694984d4d277a390ddd 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3212,7 +3212,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -578,7 +582,7 @@ index a8348a073682eec31990e9ab963b11ad32cf8bf8..8ce6f3f1a931628e018ce9a2e0c404b8
this.setSpeed(this.getRiddenSpeed(player));
this.travel(riddenInput);
} else {
@@ -4046,7 +4046,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -4062,7 +4062,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
// Paper start - lag compensate eating
// we add 1 to the expected time to avoid lag compensating when we should not
final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L));
@@ -587,7 +591,7 @@ index a8348a073682eec31990e9ab963b11ad32cf8bf8..8ce6f3f1a931628e018ce9a2e0c404b8
this.useItemRemaining = 0;
// Paper end - lag compensate eating
this.completeUsingItem();
@@ -4223,6 +4223,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -4239,6 +4239,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
this.stopUsingItem();
}
@@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 3 Oct 2025 19:43:36 +0800
Subject: [PATCH] Modify merge ItemEntity logic
Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius, when the merge radius is large and stacks containing many items get stuck in an unexpected position, individual items may never reach their destination. This configuration option is added to fix this behavior.
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index e5e8c752129a6ebb0dd1315c9b8ec459be11ef07..dfd202a74ec7f2cdb9cdc208a6428090a110f811 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -295,7 +295,7 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
ItemStack item = this.getItem();
ItemStack item1 = itemEntity.getItem();
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
- if (item1.getCount() < item.getCount()) {
+ if (fun.bm.lophine.config.modules.misc.ItemEntityConfig.followTickSequenceMerge || item1.getCount() < item.getCount()) { // Lophine - add follow Tick Sequence Merge, see Paper#13073
merge(this, item, itemEntity, item1);
} else {
merge(itemEntity, item1, this, item);
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 16:51:01 +0800
Subject: [PATCH] Leaves: Syncmatica Protocol
This patch is Powered by Syncmatica(https://github.com/End-Tech/syncmatica)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index e17f9629369f8653b484b4cc71de4874b5faa4d6..9be4bc9e78c22c12ba594b16dac6901023f0fd47 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -330,9 +330,12 @@ public class ServerGamePacketListenerImpl
this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile);
this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat
this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event
+ this.exchangeTarget = new org.leavesmc.leaves.protocol.syncmatica.exchange.ExchangeTarget(this); // Leaves - Syncmatica Protocol
this.playerGameConnection = new io.papermc.paper.connection.PaperPlayerGameConnection(this); // Paper
}
+ public final org.leavesmc.leaves.protocol.syncmatica.exchange.ExchangeTarget exchangeTarget; // Leaves - Syncmatica Protocol
+
// Paper start - configuration phase API
@Override
public io.papermc.paper.connection.PlayerCommonConnection getApiConnection() {
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 13:03:42 +0800
Subject: [PATCH] Leaves: BBOR Protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 29788fedd54b8411c9c8872b4d83b037874fb5f0..24af6821694768058dc0146220877ab70066b5f9 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -754,6 +754,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
public void setLoaded(boolean loaded) {
this.loaded = loaded;
+ // Leaves start - bbor
+ if (loaded) {
+ org.leavesmc.leaves.protocol.BBORProtocol.onChunkLoaded(this);
+ }
+ // Leaves end - bbor
}
public Level getLevel() {
@@ -0,0 +1,114 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 13:33:19 +0800
Subject: [PATCH] Leaves: Jade Protocol
This patch is Powered by Jade(https://github.com/Snownee/Jade)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
index c1798db2972c8f2a343cf6e16fd9354ff212d906..a8d617b16ab2b2c0cdb289a0aa05fa171940cd7e 100644
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
@@ -63,7 +63,7 @@ public class Armadillo extends Animal {
public final AnimationState rollOutAnimationState = new AnimationState();
public final AnimationState rollUpAnimationState = new AnimationState();
public final AnimationState peekAnimationState = new AnimationState();
- private int scuteTime;
+ public int scuteTime; // Leaves - private -> public
private boolean peekReceivedClient = false;
public Armadillo(EntityType<? extends Animal> entityType, Level level) {
diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java
index 17f58246849ed407821a987b200cc765eb7943f9..ac27df3ba0ce9bbdf2f32ea87171fbb9407008d6 100644
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
@@ -254,7 +254,7 @@ public class Tadpole extends AbstractFish {
}
}
- private int getTicksLeftUntilAdult() {
+ public int getTicksLeftUntilAdult() { // Leaves - private -> public
return Math.max(0, ticksToBeFrog - this.age);
}
diff --git a/net/minecraft/world/level/storage/loot/LootPool.java b/net/minecraft/world/level/storage/loot/LootPool.java
index 6901e629d941e22e64d83eed4e8cfee3165a96a1..fdc26c8d8c82c20534c57af2a0281b99998cc9f6 100644
--- a/net/minecraft/world/level/storage/loot/LootPool.java
+++ b/net/minecraft/world/level/storage/loot/LootPool.java
@@ -37,7 +37,7 @@ public class LootPool {
)
.apply(instance, LootPool::new)
);
- private final List<LootPoolEntryContainer> entries;
+ public final List<LootPoolEntryContainer> entries; // Leaves - private -> public
private final List<LootItemCondition> conditions;
private final Predicate<LootContext> compositeCondition;
private final List<LootItemFunction> functions;
diff --git a/net/minecraft/world/level/storage/loot/LootTable.java b/net/minecraft/world/level/storage/loot/LootTable.java
index 8612cdf7161f8ddff60a6478cc901318b8f958ba..07a962d647baa99b0e1bf3898a07cc914e91397e 100644
--- a/net/minecraft/world/level/storage/loot/LootTable.java
+++ b/net/minecraft/world/level/storage/loot/LootTable.java
@@ -50,7 +50,7 @@ public class LootTable {
public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of());
private final ContextKeySet paramSet;
private final Optional<ResourceLocation> randomSequence;
- private final List<LootPool> pools;
+ public final List<LootPool> pools; // Leaves - private -> public
private final List<LootItemFunction> functions;
private final BiFunction<ItemStack, LootContext, ItemStack> compositeFunction;
public org.bukkit.craftbukkit.CraftLootTable craftLootTable; // CraftBukkit
diff --git a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
index eeaa49e9f70a18b5d39493aeff73f31b05ac2faa..8cd0403d7873c4c37caef75935b06b056c3d951d 100644
--- a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
+++ b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
@@ -16,7 +16,7 @@ public abstract class CompositeEntryBase extends LootPoolEntryContainer {
return "Empty children list";
}
};
- protected final List<LootPoolEntryContainer> children;
+ public final List<LootPoolEntryContainer> children; // Leaves - private -> public
private final ComposableEntryContainer composedChildren;
protected CompositeEntryBase(List<LootPoolEntryContainer> children, List<LootItemCondition> conditions) {
diff --git a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
index 65e27bce9e59ef97bc8b914d646fba924d0f0877..a49bdcdf37b351436e0ba6d7865f10827c4e6ab4 100644
--- a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
+++ b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
@@ -14,7 +14,7 @@ import net.minecraft.world.level.storage.loot.predicates.ConditionUserBuilder;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
public abstract class LootPoolEntryContainer implements ComposableEntryContainer {
- protected final List<LootItemCondition> conditions;
+ public final List<LootItemCondition> conditions; // Leaves - private -> public
private final Predicate<LootContext> compositeCondition;
protected LootPoolEntryContainer(List<LootItemCondition> conditions) {
diff --git a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
index 141026601cd9a4561426b85fd1f8e7dc0544fbd7..a5d7ebb93c147bf0f806ac3c9b2dc4b878573944 100644
--- a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
+++ b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
@@ -29,7 +29,7 @@ public class NestedLootTable extends LootPoolSingletonContainer {
return "->{inline}";
}
};
- private final Either<ResourceKey<LootTable>, LootTable> contents;
+ public final Either<ResourceKey<LootTable>, LootTable> contents; // Leaves - private -> public
private NestedLootTable(
Either<ResourceKey<LootTable>, LootTable> contents, int weight, int quality, List<LootItemCondition> conditions, List<LootItemFunction> functions
diff --git a/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java b/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
index bae72197acc929c7ed3e964f156115d728eb2176..8f3094f42f3366a1313d70c0b27fbe5632b2082a 100644
--- a/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
+++ b/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
@@ -12,7 +12,7 @@ import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.ValidationContext;
public abstract class CompositeLootItemCondition implements LootItemCondition {
- protected final List<LootItemCondition> terms;
+ public final List<LootItemCondition> terms; // Leaves - private -> public
private final Predicate<LootContext> composedPredicate;
protected CompositeLootItemCondition(List<LootItemCondition> terms, Predicate<LootContext> composedPredicate) {
@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Fri, 7 Feb 2025 14:23:43 +0800
Subject: [PATCH] Leaves: Xaero Map Protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 908ec29a6e285122d1a8a43dc547b74af2697442..1bf1731e43278b71423fee5d92401c48d6dabaca 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1247,6 +1247,7 @@ public abstract class PlayerList {
player.connection.send(new ClientboundInitializeBorderPacket(worldBorder));
player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
+ org.leavesmc.leaves.protocol.XaeroMapProtocol.onSendWorldInfo(player); // Leaves - xaero map protocol
if (level.isRaining()) {
// CraftBukkit start - handle player weather
// player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F));
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Thu, 27 Mar 2025 13:04:35 +0800
Subject: [PATCH] Leaves: Support REI protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
index 9bc0a9c3577d63a0ad5489bfd4c07d5006245c5f..bb2e891539b7eb49dc7925630695149aa531f672 100644
--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
+++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
@@ -83,6 +83,12 @@ public class SmithingTransformRecipe implements SmithingRecipe {
);
}
+ // Leaves start - REI
+ public SlotDisplay getResult() {
+ return this.result.display();
+ }
+ // Leaves end - REI
+
// CraftBukkit start
@Override
public org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id) {
diff --git a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
index c324896afc2ee28ebb4d426ce4a469ee847ce24d..d5b26ff7be916e07e1162536cb2ddf5674c82f46 100644
--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
+++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
@@ -85,6 +85,12 @@ public class SmithingTrimRecipe implements SmithingRecipe {
return Optional.of(this.addition);
}
+ // Leaves start
+ public Holder<TrimPattern> pattern() {
+ return pattern;
+ }
+ // Leaves end
+
@Override
public RecipeSerializer<SmithingTrimRecipe> getSerializer() {
return RecipeSerializer.SMITHING_TRIM;
@@ -0,0 +1,95 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 27 Oct 2025 15:38:29 +0800
Subject: [PATCH] Leaves: Wool Hopper Counter
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: MIT
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index d4fe03fd766caca1d7693a5317460ca1a9b9fa4f..a821deaa5c076151336762d17a8da45abb4c43cd 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -232,8 +232,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
}
+ // Leaves start - Wool hopper counter
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockEntity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
+ if (woolColor != null) {
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ flag |= suckInItems(level, blockEntity);
+ if (!flag) {
+ break;
+ } else {
+ woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos));
+ }
+ }
+ }
+ }
+ // Leaves end - Wool hopper counter
+
if (flag) {
blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
+ // Leaves start - Wool hopper counter
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
+ blockEntity.setCooldown(0);
+ return true;
+ }
+ // Leaves end - Wool hopper counter
setChanged(level, pos, state);
// Leaves start - Lithium Sleeping Block Entity
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
@@ -465,6 +487,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
// Paper end - Perf: Optimize Hoppers
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
+ // Leaves start - hopper counter
+ if (org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ if (woolHopperCounter(level, pos, level.getBlockState(pos), HopperBlockEntity.getContainerAt(level, pos))) {
+ return true;
+ }
+ }
+ // Leaves end - hopper counter
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
if (attachedContainer == null) {
return false;
@@ -541,6 +570,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
+ // Leaves start - hopper counter
+ private static boolean woolHopperCounter(Level level, BlockPos blockPos, BlockState state, @Nullable Container container) {
+ if (container == null) {
+ return false;
+ }
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockPos.relative(state.getValue(HopperBlock.FACING)));
+ if (woolColor != null) {
+ for (int i = 0; i < container.getContainerSize(); ++i) {
+ if (!container.getItem(i).isEmpty()) {
+ ItemStack itemstack = container.getItem(i);
+ org.leavesmc.leaves.util.HopperCounter.getCounter(woolColor).add(level, itemstack);
+ container.setItem(i, ItemStack.EMPTY);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ // Leaves end - hopper counter
+
private static int[] getSlots(Container container, Direction direction) {
if (container instanceof WorldlyContainer worldlyContainer) {
return worldlyContainer.getSlotsForFace(direction);
@@ -683,6 +732,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static boolean addItem(Container container, ItemEntity item) {
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && item.isRemoved()) return false; // Leaves - Wool hopper counter
boolean flag = false;
// CraftBukkit start
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 5d05a8a843e605b6cb6d16883d17dd73d4c21e06..57ea85aebc72eb002d3dcf04144499feeb82081a 100644
index 4dde33c872d463bf17ba03e926de90e6988444b2..de72f36bd22e2c7452b9c3ee40657f6119ca70b3 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -497,6 +497,7 @@ public final class CraftServer implements Server {
@@ -8,19 +8,13 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..cc8686b791f4c559e51bb06b52b02e295b6e0547 100644
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6f9f62263 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -47,6 +47,23 @@ class PaperEventManager {
throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously.");
}
@@ -36,6 +36,15 @@ class PaperEventManager {
+ // Leaves start - skip bot
+ if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot) {
+ return;
+ }
+ // Leaves end - skip bot
+
// SimplePluginManager
public void callEvent(@NotNull Event event) {
+ // Leaves start - process bot load/save
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable && fun.bm.lophine.config.modules.function.FakeplayerConfig.canResident) {
+ if (event instanceof org.bukkit.event.world.WorldLoadEvent worldLoadEvent) {
@@ -30,7 +24,18 @@ index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..cc8686b791f4c559e51bb06b52b02e29
+ }
+ }
+ // Leaves end - process bot load/save
+
// Leaf start - Skip event if no listeners
RegisteredListener[] listeners = event.getHandlers().getRegisteredListeners();
if (listeners.length == 0) return;
@@ -47,6 +56,12 @@ class PaperEventManager {
throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously.");
}
+ // Leaves start - skip bot
+ if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot) {
+ return;
+ }
+ // Leaves end - skip bot
+
for (RegisteredListener registration : listeners) {
if (!registration.getPlugin().isEnabled()) {
@@ -48,7 +53,7 @@ index 0a10f49ee410d93e95ceb90108200a1a9d12b54b..d2eee37d810a6d5cf514bc71dea66a4d
if (nmsEntity.level() != this.getHandle().getLevel()) {
nmsEntity = nmsEntity.teleport(new TeleportTransition(this.getHandle().getLevel(), nmsEntity, TeleportTransition.DO_NOTHING));
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 57ea85aebc72eb002d3dcf04144499feeb82081a..e03de696e7652b7e211bf61ff6d6cdf44a587146 100644
index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c3c89e815 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -316,6 +316,7 @@ public final class CraftServer implements Server {
@@ -156,7 +161,7 @@ index 852e1ffef6a022caad7c8eff34091e50112a2290..8eb5d014d9ed688ffebaffb4ce0bb408
if (entity instanceof EnderDragonPart complexPart) {
if (complexPart.parentMob instanceof EnderDragon) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index ffb10b412d19907e6f63b7e3ca67ef061eec96ba..de14df49b11f1243de9aa6870a3c8e3f429502fd 100644
index 317837a2a9b3b511b5cac4df4db248d4652816dc..a8253d1a3129c8258e9ead7c430e1bcf82f735d7 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -897,7 +897,11 @@ public class CraftEventFactory {
@@ -0,0 +1,41 @@
package fun.bm.lophine.command.counter;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.command.counter.sub.DisplayCommand;
import fun.bm.lophine.command.counter.sub.ResetCommand;
import fun.bm.lophine.command.counter.sub.ToggleCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.RootNode;
import org.leavesmc.leaves.util.HopperCounter;
public class CounterCommand extends RootNode {
private final String PERM_BASE;
public CounterCommand() {
super("counter", "lophine.commands.counter");
this.PERM_BASE = "lophine.commands.counter";
children(
new ToggleCommand(this),
new ResetCommand(this),
new DisplayCommand(this)
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
Component.text("Hopper Counter: ", NamedTextColor.GRAY),
Component.text(HopperCounter.isEnabled(), HopperCounter.isEnabled() ? NamedTextColor.AQUA : NamedTextColor.GRAY)
));
return true;
}
public boolean hasPermission(@NotNull CommandSender sender, String... subcommand) {
return hasPermission(PERM_BASE, sender, subcommand);
}
}
@@ -0,0 +1,24 @@
package fun.bm.lophine.command.counter;
import net.minecraft.commands.CommandSourceStack;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.LiteralNode;
public class CounterSubCommand extends LiteralNode {
protected final CounterCommand parent;
protected CounterSubCommand(String name, CounterCommand parent) {
super(name);
this.parent = parent;
}
@Override
public boolean requires(@NotNull CommandSourceStack source) {
return hasPermission(source.getSender());
}
protected boolean hasPermission(CommandSender sender) {
return parent.hasPermission(sender, this.name);
}
}
@@ -0,0 +1,91 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.DyeColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
import java.util.concurrent.CompletableFuture;
public class DisplayCommand extends CounterSubCommand {
public DisplayCommand(CounterCommand parent) {
super("display", parent);
children(
DyeColorArg::new
);
}
public static void displayCounter(CommandContext context, @NotNull HopperCounter counter, boolean realTime) {
for (Component component : counter.format(MinecraftServer.getServer(), context.getSource().getLevel(), realTime)) {
context.getSender().sendMessage(component);
}
}
private static class DyeColorArg extends ArgumentNode<String> {
protected DyeColorArg() {
super("color", StringArgumentType.string());
children(
TimeArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
displayCounter(context, counter, false);
return true;
}
@Override
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
for (DyeColor value : DyeColor.values()) {
String color = value.getName();
if (color.startsWith(path)) {
builder.suggest(color);
}
}
return builder.buildFuture();
}
private static class TimeArg extends ArgumentNode<String> {
protected TimeArg() {
super("time", StringArgumentType.string());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
String timeType = context.getArgument(TimeArg.class);
switch (timeType) {
case "realtime" -> displayCounter(context, counter, true);
case "gametick" -> displayCounter(context, counter, false);
default ->
context.getSender().sendMessage(Component.text("Invalid time type: " + timeType, NamedTextColor.RED));
}
return true;
}
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
builder.suggest("realtime");
builder.suggest("gametick");
return builder.buildFuture();
}
}
}
}
@@ -0,0 +1,75 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.format.TextColor;
import net.minecraft.world.item.DyeColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
import java.util.concurrent.CompletableFuture;
public class ResetCommand extends CounterSubCommand {
public ResetCommand(CounterCommand parent) {
super("reset", parent);
children(
DyeColorArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
HopperCounter.resetAll(context.getSource().getLevel(), false);
context.getSender().sendMessage(Component.text("Restarted all counters."));
return true;
}
private static class DyeColorArg extends ArgumentNode<String> {
protected DyeColorArg() {
super("color", StringArgumentType.string());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
if (color0.equals("all")) {
HopperCounter.resetAll(context.getSource().getLevel(), false);
context.getSender().sendMessage(Component.text("Restarted all counters."));
return true;
}
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
counter.reset(context.getSource().getLevel());
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
Component.text("Restarted "),
Component.text(color.getName(), TextColor.color(color.getTextColor())),
Component.text(" counter.")
));
return true;
}
@Override
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
if ("all".startsWith(path)) {
builder.suggest("all");
}
for (DyeColor value : DyeColor.values()) {
String color = value.getName();
if (color.startsWith(path)) {
builder.suggest(color);
}
}
return builder.buildFuture();
}
}
}
@@ -0,0 +1,55 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
public class ToggleCommand extends CounterSubCommand {
public ToggleCommand(CounterCommand parent) {
super("toggle", parent);
children(
BooleanArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
if (!HopperCounter.isEnabled()) {
HopperCounter.setEnabled(true);
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
} else {
HopperCounter.setEnabled(false);
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
}
return true;
}
private static class BooleanArg extends ArgumentNode<Boolean> {
protected BooleanArg() {
super("enabled", BoolArgumentType.bool());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
boolean enabled = context.getArgument(BooleanArg.class);
if (enabled == HopperCounter.isEnabled()) {
context.getSender().sendMessage(Component.text("Hopper Counter is already " + (enabled ? "enabled" : "disabled") + ".", NamedTextColor.GRAY));
} else {
HopperCounter.setEnabled(enabled);
if (enabled) {
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
} else {
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
}
}
return true;
}
}
}
@@ -3,18 +3,30 @@ package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "command")
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "command")
public class CommandConfig implements IConfigModule {
@ConfigInfo(baseName = "tick_command_enabled", comments =
@ConfigInfo(name = "tick_command_enabled", comments =
"""
Allow to use tick command""")
public static boolean tick = false;
@ConfigInfo(baseName = "datapack_command_enabled", comments =
@ConfigInfo(name = "function_command_enabled", comments =
"""
Allow to use datapack command
--- datapack hot-update unsupported, please restart server""")
public static boolean datapack = false;
Allow to use function command""")
public static boolean function = false;
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint bar"})
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
@ConfigInfo(name = "waypoint_command_enabled", comments =
"""
Allow to use waypoint command""")
public static boolean waypoint = false;
@ConfigInfo(name = "scoreboard_command_enabled", comments =
"""
Allow to use scoreboard command""")
public static boolean scoreboard = false;
}
@@ -5,9 +5,9 @@ import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "entity_damage_source_trace")
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "entity_damage_source_trace")
public class EntityDamageSourceTraceConfig implements IConfigModule {
@ConfigInfo(baseName = "enabled", comments =
@ConfigInfo(name = "enabled", comments =
"""
Allow trace damage source cross different Region Scheduler.""")
public static boolean enabled = false;
@@ -5,16 +5,16 @@ import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "ray_tracking_entity_tracker")
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "ray_tracking_entity_tracker")
public class RayTrackingEntityTrackerConfig implements IConfigModule {
@ConfigInfo(baseName = "enabled")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(baseName = "skip_marker_armor_stands")
@ConfigInfo(name = "skip_marker_armor_stands")
public static boolean skipMarkerArmorStands = true;
@ConfigInfo(baseName = "check_interval_ms")
@ConfigInfo(name = "check_interval_ms")
public static int checkIntervalMs = 10;
@ConfigInfo(baseName = "tracing_distance")
@ConfigInfo(name = "tracing_distance")
public static int tracingDistance = 48;
@ConfigInfo(baseName = "hitbox_limit")
@ConfigInfo(name = "hitbox_limit")
public static int hitboxLimit = 50;
}
@@ -1,16 +0,0 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "waypoint_bar")
public class WaypointConfig implements IConfigModule {
@TransformedConfig(name = "enable-waypoint", category = {"experiment", "waypoint bar"})
@ConfigInfo(baseName = "enabled", comments =
"""
Enable waypoint bar unsafe""")
public static boolean forceEnableWaypointUnsafe = false;
}
@@ -6,10 +6,10 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FIXES, mainName = "end-void-ring")
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "end-void-ring")
public class EndVoidRingsConfig implements IConfigModule {
@TransformedConfig(name = "enabled", category = {"gameplay", "end_void_rings"})
@ConfigInfo(baseName = "enabled", comments = """
@TransformedConfig(name = "enabled", directory = {"gameplay", "end_void_rings"})
@ConfigInfo(name = "enabled", comments = """
If enabled, it will generate end void rings, like MC-159283.""")
public static boolean enabled = false;
}
@@ -1,32 +1,38 @@
package fun.bm.lophine.config.modules.function;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.CommandSuggestions;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "container_expansion")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "container_expansion")
public class ContainerExpansionConfig implements IConfigModule {
@TransformedConfig(name = "barrel_rows", category = {"misc", "container_expansion"})
@ConfigInfo(baseName = "barrel_rows", comments =
@TransformedConfig(name = "barrel_rows", directory = {"misc", "container_expansion"})
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "barrel_rows", comments =
"""
range: 1~6""")
public static int barrelRows = 3;
@TransformedConfig(name = "enderchest_rows", category = {"misc", "container_expansion"})
@ConfigInfo(baseName = "enderchest_rows", comments =
@TransformedConfig(name = "enderchest_rows", directory = {"misc", "container_expansion"})
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "enderchest_rows", comments =
"""
range: 1~6""")
public static int enderchestRows = 3;
@TransformedConfig(name = "shulker_stackable_count", category = {"misc", "container_expansion"})
@ConfigInfo(baseName = "shulker_stackable_count", comments =
@TransformedConfig(name = "shulker_stackable_count", directory = {"function", "container_expansion"})
@TransformedConfig(name = "shulker_stackable_count", directory = {"misc", "container_expansion"})
@CommandSuggestions(suggest = {"1", "2", "32", "64"})
@ConfigInfo(name = "shulker_stackable_count", directory = {"shulker_box"}, comments =
"""
range: 1~64""")
public static int shulkerCount = 1;
@TransformedConfig(name = "same_nbt_shulker_stackable", category = {"misc", "container_expansion"})
@ConfigInfo(baseName = "same_nbt_shulker_stackable")
@TransformedConfig(name = "same_nbt_shulker_stackable", directory = {"function", "container_expansion"})
@TransformedConfig(name = "same_nbt_shulker_stackable", directory = {"misc", "container_expansion"})
@ConfigInfo(name = "same_nbt_shulker_stackable", directory = {"shulker_box"})
public static boolean nbtShulkerStackable = false;
}
@@ -5,104 +5,107 @@ import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import net.minecraft.server.MinecraftServer;
import org.bukkit.Bukkit;
import org.leavesmc.leaves.bot.BotCommand;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.Actions;
import org.leavesmc.leaves.command.bot.BotCommand;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "fakeplayer")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(baseName = "enable", comments = """
@ConfigInfo(name = "enable", comments = """
Enable fakeplayer functionality""")
public static boolean enable = true;
@ConfigInfo(baseName = "unable-fakeplayer-names", comments = """
@ConfigInfo(name = "unable-fakeplayer-names", comments = """
List of names that cannot be used for fakeplayers""")
public static List<String> unableNames = List.of("player-name");
@ConfigInfo(baseName = "limit", comments = """
@ConfigInfo(name = "limit", comments = """
Maximum number of fakeplayers allowed""")
public static int limit = 10;
@ConfigInfo(baseName = "prefix", comments = """
@ConfigInfo(name = "prefix", comments = """
Prefix for fakeplayer names""")
public static String prefix = "";
@ConfigInfo(baseName = "suffix", comments = """
@ConfigInfo(name = "suffix", comments = """
Suffix for fakeplayer names""")
public static String suffix = "";
@ConfigInfo(baseName = "regen-amount", comments = """
@ConfigInfo(name = "regen-amount", comments = """
Regeneration amount for fakeplayers""")
public static double regenAmount = 0.0;
@ConfigInfo(baseName = "resident-fakeplayer", comments = """
@ConfigInfo(name = "resident-fakeplayer", comments = """
Allow fakeplayers to be resident""")
public static boolean canResident = false;
@ConfigInfo(baseName = "open-fakeplayer-inventory", comments = """
@ConfigInfo(name = "open-fakeplayer-inventory", comments = """
Allow opening fakeplayer inventory""")
public static boolean canOpenInventory = false;
@ConfigInfo(baseName = "use-action", comments = """
@ConfigInfo(name = "use-action", comments = """
Allow fakeplayers to use actions""")
public static boolean canUseAction = true;
@ConfigInfo(baseName = "modify-config", comments = """
@ConfigInfo(name = "modify-config", comments = """
Allow modifying fakeplayer config""")
public static boolean canModifyConfig = false;
@ConfigInfo(baseName = "manual-save-and-load", comments = """
@ConfigInfo(name = "manual-save-and-load", comments = """
Allow manual save and load of fakeplayers""")
public static boolean canManualSaveAndLoad = false;
@ConfigInfo(baseName = "cache-skin", comments = """
@ConfigInfo(name = "cache-skin", comments = """
Use skin cache for fakeplayers""")
public static boolean useSkinCache = false;
@ConfigInfo(baseName = "always-send-data", comments = """
@ConfigInfo(name = "always-send-data", comments = """
Always send data for fakeplayers""")
public static boolean canSendDataAlways = true;
@ConfigInfo(baseName = "skip-sleep-check", comments = """
@ConfigInfo(name = "skip-sleep-check", comments = """
Skip sleep check for fakeplayers""")
public static boolean canSkipSleep = false;
@ConfigInfo(baseName = "spawn-phantom", comments = """
@ConfigInfo(name = "spawn-phantom", comments = """
Allow phantoms to spawn for fakeplayers""")
public static boolean canSpawnPhantom = false;
@ConfigInfo(baseName = "simulation-distance", comments = """
@ConfigInfo(name = "simulation-distance", comments = """
Simulation distance for fakeplayers (-1 for default)""")
public static int simulationDistance = -1;
@ConfigInfo(baseName = "enable-locator-bar", comments = """
@ConfigInfo(name = "enable-locator-bar", comments = """
Enable locator bar for fakeplayers""")
public static boolean enableLocatorBar = false;
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
public static void unregisterCommand(String name) {
name = name.toLowerCase(Locale.ENGLISH).trim();
MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove(name);
MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove("leaves:" + name);
MinecraftServer.getServer().server.syncCommands();
}
private BotCommand command = null;
private boolean registered = false;
public static int getSimulationDistance(ServerBot bot) {
return simulationDistance == -1 ? bot.getBukkitEntity().getSimulationDistance() : simulationDistance;
}
public void onLoaded(CommentedFileConfig configInstance) {
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enable) {
Bukkit.getCommandMap().register("bot", "lophine", new BotCommand());
Actions.registerAll();
} else {
unregisterCommand("bot");
command = new BotCommand();
command.register();
registered = true;
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (registered) {
command.unregister();
command = null;
}
}
}
@@ -6,10 +6,10 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "language")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "language")
public class LanguageConfig implements IConfigModule {
@TransformedConfig(name = "lang", category = {"optimizations", "language"})
@ConfigInfo(baseName = "lang", comments = """
@TransformedConfig(name = "lang", directory = {"optimizations", "language"})
@ConfigInfo(name = "lang", comments = """
Please use the key from https://minecraft.wiki/w/Language
Sample of format: en_us zh_cn zh_hk zh_tw""")
public static String lang = "en_us";
@@ -6,22 +6,30 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "old-feature")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "old-feature")
public class OldFeatureConfig implements IConfigModule {
@TransformedConfig(name = "spawn_invulnerable_time", category = {"misc", "old-feature"})
@ConfigInfo(baseName = "spawn_invulnerable_time")
@TransformedConfig(name = "spawn_invulnerable_time", directory = {"misc", "old-feature"})
@ConfigInfo(name = "spawn_invulnerable_time")
public static boolean spawnInvulnerableTime = false;
@TransformedConfig(name = "old_zombie_reinforcement", category = {"misc", "old-feature"})
@ConfigInfo(baseName = "old_zombie_reinforcement")
@TransformedConfig(name = "old_zombie_reinforcement", directory = {"misc", "old-feature"})
@ConfigInfo(name = "old_zombie_reinforcement")
public static boolean oldZombieReinforcement = false;
@TransformedConfig(name = "old_explosion_damage_calculator", category = {"misc", "old-feature"})
@ConfigInfo(baseName = "old_explosion_damage_calculator")
@TransformedConfig(name = "old_explosion_damage_calculator", directory = {"misc", "old-feature"})
@ConfigInfo(name = "old_explosion_damage_calculator")
public static boolean oldExplosionDamageCalculator = false;
@TransformedConfig(name = "old_raid_behavior", category = {"misc", "old-feature"})
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", category = {"misc", "revert_raid_changes"}, transformComments = false)
@ConfigInfo(baseName = "old_raid_behavior")
@TransformedConfig(name = "old_raid_behavior", directory = {"misc", "old-feature"})
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", directory = {"misc", "revert_raid_changes"}, transformComments = false)
@ConfigInfo(name = "old_raid_behavior")
public static boolean oldRaidBehavior = false;
@TransformedConfig(name = "villager-infinite-trade", directory = {"function", "villager"}, transformComments = false)
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager"}, transformComments = false)
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager-config"}, transformComments = false)
@ConfigInfo(name = "villager-void-trade", comments =
"""
Allow villager void trade.""")
public static boolean villagerVoidTrade = false;
}
@@ -6,11 +6,11 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "redstone")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@TransformedConfig(name = "shears_rotate", category = {"misc", "redstone"})
@TransformedConfig(name = "allow_skip_cooldown", category = {"misc", "redstone"})
@ConfigInfo(baseName = "shears_rotate", comments =
@TransformedConfig(name = "shears_rotate", directory = {"misc", "redstone"})
@TransformedConfig(name = "allow_skip_cooldown", directory = {"misc", "redstone"})
@ConfigInfo(name = "shears_rotate", comments =
"""
Allows you to use the Shears to right-click to rotate the block.""")
public static boolean shears = false;
@@ -1,48 +0,0 @@
package fun.bm.lophine.config.modules.function;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(configAttribution = EnumConfigCategory.FUNCTION, mainName = "survux-protocol")
public class SurvuxProtocolConfig implements IConfigModule {
@TransformedConfig(name = "entity-protocol", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "entity-protocol")
public static boolean entityProtocol = false;
@TransformedConfig(name = "hud-logger-protocol", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "hud-logger-protocol")
public static boolean hudLoggerProtocol = false;
@TransformedConfig(name = "hud-metadata-protocol", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "hud-metadata-protocol")
public static boolean hudMetadataProtocol = false;
@TransformedConfig(name = "hud-metadata-share-seed", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "hud-metadata-share-seed")
public static boolean hudMetadataShareSeed = false;
@TransformedConfig(name = "structure-protocol", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "structure-protocol")
public static boolean structureProtocol = false;
@TransformedConfig(name = "hud-enabled-loggers", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "hud-enabled-loggers")
public static List<String> hudEnabledLoggers = List.of("tps", "mob_caps");
@TransformedConfig(name = "hud-update-interval", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "hud-update-interval")
public static int hudUpdateInterval = 1;
@TransformedConfig(name = "litematics-enabled", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "litematics-enabled")
public static boolean litematicsEnabled = false;
@TransformedConfig(name = "litematics-max-nbt-size", category = {"misc", "survux-protocol"})
@ConfigInfo(baseName = "litematics-max-nbt-size")
public static int litematicsMaxNbtSize = 2097152;
}
@@ -1,18 +0,0 @@
package fun.bm.lophine.config.modules.function;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "villager")
public class VillagerConfig implements IConfigModule {
@TransformedConfig(name = "villager-infinite-trade", category = {"misc", "villager"})
@TransformedConfig(name = "villager-infinite-trade", category = {"misc", "villager-config"})
@ConfigInfo(baseName = "villager-infinite-trade", comments =
"""
Allow villager infinite trade (limit of 524288 times)
---- we won't edit saved data, only edit in send data to client.""")
public static boolean villagerInfiniteTrade = false;
}
@@ -0,0 +1,31 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.command.counter.CounterCommand;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
public class WoolHopperCounterConfig implements IConfigModule {
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "unlimited-speed")
public static boolean unlimitedSpeed = false;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enabled) new CounterCommand().register();
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
Bukkit.getCommandMap().getKnownCommands().remove("luminol:tpsbar");
}
}
@@ -0,0 +1,16 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "appleskin", directory = {"protocol"})
public class AppleSkinProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable AppleSkin protocol support""")
public static boolean enabled = false;
@ConfigInfo(name = "sync-tick-interval", comments = """
Set AppleSkin Synchronization Frequency (Unit: Game Ticks)""")
public static int syncTickInterval = 20;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "bbor", directory = {"protocol"})
public class BBORProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable BBOR protocol support""")
public static boolean enabled = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "jade", directory = {"protocol"})
public class JadeProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Jade protocol support""")
public static boolean enabled = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "rei", directory = {"protocol"})
public class REIServerProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Roughly Enough Items protocol support""")
public static boolean enabled = false;
}
@@ -0,0 +1,74 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.CommandSuggestions;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "servux", directory = {"protocol"})
public class ServuxProtocolConfig implements IConfigModule {
@TransformedConfig(name = "entity-protocol", directory = {"function", "servux-protocol", "data"})
@TransformedConfig(name = "entity-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "entity-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "entity-protocol", directory = {"data"})
public static boolean entityProtocol = false;
@TransformedConfig(name = "hud-logger-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-logger-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-logger-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-logger-protocol")
public static boolean hudLoggerProtocol = false;
@TransformedConfig(name = "hud-metadata-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-metadata-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-protocol")
public static boolean hudMetadataProtocol = false;
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-share-seed")
public static boolean hudMetadataShareSeed = false;
@TransformedConfig(name = "structure-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "structure-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "structure-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "structure-protocol")
public static boolean structureProtocol = false;
@TransformedConfig(name = "hud-enabled-loggers", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-enabled-loggers", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-enabled-loggers", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-enabled-loggers")
public static List<String> hudEnabledLoggers = List.of("tps", "mob_caps");
@TransformedConfig(name = "hud-update-interval", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-update-interval", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-update-interval", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-update-interval")
public static int hudUpdateInterval = 1;
@TransformedConfig(name = "litematics-enabled", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-enabled", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-enabled", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "litematics-enabled", directory = {"litematics"})
public static boolean litematicsEnabled = false;
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"misc", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "2097152"})
@ConfigInfo(name = "litematics-max-nbt-size", directory = {"litematics"})
public static int litematicsMaxNbtSize = 2097152;
@TransformedConfig(name = "litematics-print-max-delay-ticks", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-print-max-delay-ticks", directory = {"function", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "1200"})
@ConfigInfo(name = "litematics-print-max-delay-ticks", directory = {"litematics"}, comments = "The max delay ticks for printing litematics, -1 to disable")
public static int maxDelay = 1200;
}
@@ -0,0 +1,28 @@
package fun.bm.lophine.config.modules.function.protocol;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.protocol.syncmatica.SyncmaticaProtocol;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "syncmatica", directory = {"protocol"})
public class SyncmaticaProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Syncmatica protocol support""")
public static boolean enabled = false;
@ConfigInfo(name = "useQuota", comments = """
Is there a limit on the size of projection files?""")
public static boolean useQuota = false;
@ConfigInfo(name = "quota-Limit", comments = """
Maximum Projection File Size (in bytes)""")
public static int quotaLimit = 40000000;
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
SyncmaticaProtocol.init(enabled);
}
}
@@ -0,0 +1,17 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.Random;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "xaero-map", directory = {"protocol"})
public class XaeroMapProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Xaero World Map Protocol Support""")
public static boolean enabled = false;
@ConfigInfo(name = "xaeroMapServerID")
public static int xaeroMapServerID = new Random().nextInt();
}
@@ -5,13 +5,13 @@ import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "disable-check")
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "disable-check")
public class DisableCheckConfig implements IConfigModule {
@ConfigInfo(baseName = "disable-op-move-check", comments = """
@ConfigInfo(name = "disable-op-move-check", comments = """
Disable the check for the operator's move check""")
public static boolean disableOpMoveCheck = false;
@ConfigInfo(baseName = "disable-op-fly-check", comments = """
@ConfigInfo(name = "disable-op-fly-check", comments = """
Disable the check for the operator's fly check""")
public static boolean disableOpFlyCheck = false;
}
@@ -0,0 +1,16 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "item-entity")
public class ItemEntityConfig implements IConfigModule {
@ConfigInfo(name = "follow-tick-sequence-merge", comments = """
Due to Paper's modification of the merge radius,
when the merge radius is large and stacks containing many items get stuck in an unexpected position,
individual items may never reach their destination.
This configuration option is added to fix this behavior.""")
public static boolean followTickSequenceMerge = false;
}
@@ -6,20 +6,21 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(configAttribution = EnumConfigCategory.REMOVED, mainName = "removed_config")
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@TransformedConfig(name = "disable_end_crystal_check", category = {"fixes", "end_crystal"}, transform = false)
@TransformedConfig(name = "disable_end_crystal_check", category = {"misc", "end_crystal"}, transform = false)
@TransformedConfig(name = "allow_skip_cooldown", category = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "bad_omen_infinite", category = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "skip_height_check", category = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "skip_self_raid_check", category = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "use_old_position_find", category = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "vanilla_hopper", category = {"misc", "redstone"}, transform = false)
@TransformedConfig(name = "old_replaceable_by_mushrooms", category = {"misc", "old-feature"}, transform = false)
@TransformedConfig(name = "old_nether_portal_collision", category = {"misc", "old-feature"}, transform = false)
@TransformedConfig(name = "better_shulker_box", category = {"misc", "container_expansion"}, transform = false)
@ConfigInfo(baseName = "removed", comments =
@TransformedConfig(name = "datapack_command_enabled", directory = {"experiment", "command"}, transform = false)
@TransformedConfig(name = "disable_end_crystal_check", directory = {"fixes", "end_crystal"}, transform = false)
@TransformedConfig(name = "disable_end_crystal_check", directory = {"misc", "end_crystal"}, transform = false)
@TransformedConfig(name = "allow_skip_cooldown", directory = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "bad_omen_infinite", directory = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "skip_height_check", directory = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "skip_self_raid_check", directory = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "use_old_position_find", directory = {"misc", "revert_raid_changes"}, transform = false)
@TransformedConfig(name = "vanilla_hopper", directory = {"misc", "redstone"}, transform = false)
@TransformedConfig(name = "old_replaceable_by_mushrooms", directory = {"misc", "old-feature"}, transform = false)
@TransformedConfig(name = "old_nether_portal_collision", directory = {"misc", "old-feature"}, transform = false)
@TransformedConfig(name = "better_shulker_box", directory = {"misc", "container_expansion"}, transform = false)
@ConfigInfo(name = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
public static boolean enabled = true;
@@ -6,9 +6,9 @@ import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.LanguageConfig;
import io.papermc.paper.ServerBuildInfo;
import me.earthme.luminol.config.ConfigManager;
import me.earthme.luminol.config.ConfigsInstance;
import net.minecraft.DetectedVersion;
import net.minecraft.locale.DeprecatedTranslationsInfo;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.FormattedText;
@@ -41,7 +41,7 @@ import java.util.function.BiConsumer;
*/
public class ServerI18nUtil {
private static final Logger logger = LogUtils.getClassLogger();
private static final String VERSION = DetectedVersion.BUILT_IN.name();
private static final String VERSION = ServerBuildInfo.buildInfo().minecraftVersionId();
private static final String BASE_PATH = "cache/lophine/" + VERSION + "/";
private static final String defaultLophineLangPath = "/assets/lophine/lang/en_us.json";
private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
@@ -83,8 +83,8 @@ public class ServerI18nUtil {
logger.warn("Unsupported language: {}", LanguageConfig.lang);
// Fallback to English
final ConfigsInstance configsInstance = ConfigManager.configfiles.get("lophine");
configsInstance.setConfig(new String[]{"optimizations", "lang"}, "en_us");
configsInstance.reloadAsync();
configsInstance.setConfig(new String[]{"function", "language", "lang"}, "en_us");
configsInstance.reloadAsync(true);
} catch (Exception e) {
if (e instanceof MalformedJsonException malformedJson) {
malformedJson.clean();
@@ -1,504 +0,0 @@
/*
* 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;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.agent.AbstractBotConfig;
import org.leavesmc.leaves.bot.agent.Actions;
import org.leavesmc.leaves.bot.agent.Configs;
import org.leavesmc.leaves.bot.agent.actions.ServerBotAction;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.entity.bot.Bot;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.event.bot.BotConfigModifyEvent;
import org.leavesmc.leaves.event.bot.BotCreateEvent;
import org.leavesmc.leaves.event.bot.BotRemoveEvent;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import org.slf4j.Logger;
import java.util.*;
import static net.kyori.adventure.text.Component.text;
public class BotCommand extends Command {
private static final Logger LOGGER = LogUtils.getLogger();
public BotCommand() {
super("bot");
this.setPermission("lophine.bot");
this.setDescription("FakePlayer Command");
this.setUsage("/bot <create|remove|list|action|config|save|load> [args...]");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
if (!testPermission(sender)) {
return true;
}
if (!FakeplayerConfig.enable) {
sender.sendMessage(Component.text("Fakeplayer feature is disabled!").color(TextColor.color(255, 0, 0)));
return true;
}
if (args.length == 0) {
sender.sendMessage(Component.text("Usage: /bot <create|remove|list|action|config|save|load> [args...]").color(TextColor.color(255, 255, 0)));
return true;
}
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "create" -> {
return handleCreate(sender, args);
}
case "remove" -> {
return handleRemove(sender, args);
}
case "list" -> {
return handleList(sender, args);
}
case "action" -> {
return handleAction(sender, args);
}
case "config" -> {
return handleConfig(sender, args);
}
case "save" -> {
return handleSave(sender, args);
}
case "load" -> {
return handleLoad(sender, args);
}
default -> {
sender.sendMessage(Component.text("Unknown subcommand: " + subCommand).color(TextColor.color(255, 0, 0)));
sender.sendMessage(Component.text("Available commands: create, remove, list, action, config, save, load").color(TextColor.color(255, 255, 0)));
}
}
return true;
}
private boolean handleCreate(CommandSender sender, String[] args) {
if (args.length < 2) {
sender.sendMessage(text("Use /bot create <name> [skin_name] to create a fakeplayer", NamedTextColor.RED));
return true;
}
String botName = args[1];
String fullName = BotUtil.getFullName(botName);
if (this.canCreate(sender, fullName)) {
BotCreateState.Builder builder = BotCreateState.builder(botName, Bukkit.getWorlds().getFirst().getSpawnLocation())
.createReason(BotCreateEvent.CreateReason.COMMAND)
.creator(sender);
if (args.length >= 3) {
builder.skinName(args[2]);
}
if (sender instanceof Player player) {
builder.location(player.getLocation());
} else if (sender instanceof ConsoleCommandSender) {
if (args.length >= 7) {
try {
World world = Bukkit.getWorld(args[3]);
double x = Double.parseDouble(args[4]);
double y = Double.parseDouble(args[5]);
double z = Double.parseDouble(args[6]);
if (world != null) {
builder.location(new Location(world, x, y, z));
}
} catch (Exception e) {
LOGGER.warn("Can't build location", e);
}
}
}
builder.spawnWithSkin(null);
}
return true;
}
private boolean handleRemove(CommandSender sender, String[] args) {
if (args.length < 2 || args.length > 5) {
sender.sendMessage(text("Usage: /bot remove <name> [hour] [minute] [second]", NamedTextColor.RED));
return true;
}
String botName = args[1];
BotList botList = BotList.INSTANCE;
ServerBot bot = botList.getBotByName(BotUtil.getFullName(botName));
if (bot == null) {
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
return true;
}
if (args.length == 3 && args[2].equals("cancel")) {
if (bot.removeTaskId == -1) {
sender.sendMessage(text("This fakeplayer is not scheduled to be removed", NamedTextColor.RED));
return true;
}
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
bot.removeTaskId = -1;
sender.sendMessage(text("Remove cancel"));
return true;
}
if (args.length > 2) {
long time = 0;
int h;
long s = 0;
long m = 0;
try {
h = Integer.parseInt(args[2]);
if (h < 0) {
throw new NumberFormatException();
}
time += ((long) h) * 3600 * 20;
if (args.length > 3) {
m = Long.parseLong(args[3]);
if (m > 59 || m < 0) {
throw new NumberFormatException();
}
time += m * 60 * 20;
}
if (args.length > 4) {
s = Long.parseLong(args[4]);
if (s > 59 || s < 0) {
throw new NumberFormatException();
}
time += s * 20;
}
} catch (NumberFormatException e) {
sender.sendMessage(text("Usage: /bot remove <name> [hour] [minute] [second]", NamedTextColor.RED));
return true;
}
boolean isReschedule = bot.removeTaskId != -1;
if (isReschedule) {
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
}
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
bot.removeTaskId = -1;
botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false);
}, time).getTaskId();
sender.sendMessage("This fakeplayer will be removed in " + h + "h " + m + "m " + s + "s" + (isReschedule ? " (rescheduled)" : ""));
return true;
}
botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false);
sender.sendMessage(text("Removed fakeplayer: " + botName, NamedTextColor.GREEN));
return true;
}
private boolean handleList(CommandSender sender, String[] args) {
BotList botList = BotList.INSTANCE;
if (args.length < 2) {
Map<World, List<String>> botMap = new HashMap<>();
for (World world : Bukkit.getWorlds()) {
botMap.put(world, new ArrayList<>());
}
for (ServerBot bot : botList.bots) {
Bot bukkitBot = bot.getBukkitEntity();
botMap.get(bukkitBot.getWorld()).add(bukkitBot.getName());
}
sender.sendMessage("Total number: (" + botList.bots.size() + "/" + FakeplayerConfig.limit + ")");
for (World world : botMap.keySet()) {
sender.sendMessage(world.getName() + "(" + botMap.get(world).size() + "): " + formatPlayerNameList(botMap.get(world)));
}
} else {
World world = Bukkit.getWorld(args[1]);
if (world == null) {
sender.sendMessage(text("Unknown world", NamedTextColor.RED));
return true;
}
List<String> snowBotList = new ArrayList<>();
for (ServerBot bot : botList.bots) {
Bot bukkitBot = bot.getBukkitEntity();
if (bukkitBot.getWorld() == world) {
snowBotList.add(bukkitBot.getName());
}
}
sender.sendMessage(world.getName() + "(" + snowBotList.size() + "): " + formatPlayerNameList(snowBotList));
}
return true;
}
private boolean handleAction(CommandSender sender, String[] args) {
if (!FakeplayerConfig.canUseAction) {
sender.sendMessage(text("Bot action feature is disabled!", NamedTextColor.RED));
return true;
}
if (args.length < 3) {
sender.sendMessage(text("Use /bot action <name> <action> to make fakeplayer do action", NamedTextColor.RED));
return true;
}
ServerBot bot = BotList.INSTANCE.getBotByName(args[1]);
if (bot == null) {
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
return true;
}
switch (args[2].toLowerCase()) {
case "list" -> {
sender.sendMessage(bot.getScoreboardName() + "'s action list:");
for (int i = 0; i < bot.getBotActions().size(); i++) {
sender.sendMessage(i + " " + bot.getBotActions().get(i).getName());
}
}
case "start" -> executeActionStart(bot, sender, args);
case "stop" -> executeActionStop(bot, sender, args);
default -> sender.sendMessage(text("Unknown action command. Use: list, start, stop", NamedTextColor.RED));
}
return true;
}
private void executeActionStart(ServerBot bot, CommandSender sender, String[] args) {
if (args.length < 4) {
sender.sendMessage(text("Invalid action", NamedTextColor.RED));
return;
}
ServerBotAction<?> action = Actions.getForName(args[3]);
if (action == null) {
sender.sendMessage(text("Invalid action", NamedTextColor.RED));
return;
}
CraftPlayer player;
if (sender instanceof CraftPlayer) {
player = (CraftPlayer) sender;
} else {
player = bot.getBukkitEntity();
}
String[] realArgs = Arrays.copyOfRange(args, 4, args.length);
ServerBotAction<?> newAction;
try {
newAction = action.create();
newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs));
} catch (IllegalArgumentException e) {
sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED));
return;
}
if (bot.addBotAction(newAction, sender)) {
sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString());
}
}
private void executeActionStop(ServerBot bot, CommandSender sender, String[] args) {
if (args.length < 4) {
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
return;
}
String index = args[3];
if (index.equals("all")) {
Set<ServerBotAction<?>> forRemoval = new HashSet<>();
for (int i = 0; i < bot.getBotActions().size(); i++) {
ServerBotAction<?> action = bot.getBotActions().get(i);
BotActionStopEvent event = new BotActionStopEvent(
bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender
);
event.callEvent();
if (!event.isCancelled()) {
forRemoval.add(action);
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
}
}
bot.getBotActions().removeAll(forRemoval);
sender.sendMessage(bot.getScoreboardName() + "'s action list cleared.");
return;
}
try {
int i = Integer.parseInt(index);
if (i < 0 || i >= bot.getBotActions().size()) {
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
return;
}
ServerBotAction<?> action = bot.getBotActions().get(i);
BotActionStopEvent event = new BotActionStopEvent(
bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender
);
event.callEvent();
if (!event.isCancelled()) {
action.stop(bot, BotActionStopEvent.Reason.COMMAND);
bot.getBotActions().remove(i);
sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped.");
}
} catch (NumberFormatException e) {
sender.sendMessage(text("Invalid index", NamedTextColor.RED));
}
}
private boolean handleConfig(CommandSender sender, String[] args) {
if (!FakeplayerConfig.canModifyConfig) {
sender.sendMessage(text("Bot config feature is disabled!", NamedTextColor.RED));
return true;
}
if (args.length < 3) {
sender.sendMessage(text("Use /bot config <name> <config> to modify fakeplayer's config", NamedTextColor.RED));
return true;
}
ServerBot bot = BotList.INSTANCE.getBotByName(args[1]);
if (bot == null) {
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
return true;
}
if (!Configs.getConfigNames().contains(args[2])) {
sender.sendMessage(text("This config is not accept", NamedTextColor.RED));
return true;
}
AbstractBotConfig<?> config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[2])));
if (args.length < 4) {
config.getMessage().forEach(sender::sendMessage);
} else {
String[] realArgs = Arrays.copyOfRange(args, 3, args.length);
BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return true;
}
CommandArgumentResult result = config.getArgument().parse(0, realArgs);
try {
config.setFromCommand(result);
config.getChangeMessage().forEach(sender::sendMessage);
} catch (IllegalArgumentException e) {
sender.sendMessage(text(e.getMessage(), NamedTextColor.RED));
}
}
return true;
}
private boolean handleSave(CommandSender sender, String[] args) {
if (!FakeplayerConfig.canManualSaveAndLoad) {
sender.sendMessage(text("Bot save/load feature is disabled!", NamedTextColor.RED));
return true;
}
if (args.length < 2) {
sender.sendMessage(text("Use /bot save <name> to save a fakeplayer", NamedTextColor.RED));
return true;
}
BotList botList = BotList.INSTANCE;
ServerBot bot = botList.getBotByName(args[1]);
if (bot == null) {
sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED));
return true;
}
if (botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true)) {
sender.sendMessage(bot.getScoreboardName() + " saved to " + bot.createState.realName());
}
return true;
}
private boolean handleLoad(CommandSender sender, String[] args) {
if (!FakeplayerConfig.canManualSaveAndLoad) {
sender.sendMessage(text("Bot save/load feature is disabled!", NamedTextColor.RED));
return true;
}
if (args.length < 2) {
sender.sendMessage(text("Use /bot load <name> to load a fakeplayer", NamedTextColor.RED));
return true;
}
String realName = args[1];
BotList botList = BotList.INSTANCE;
if (!botList.getSavedBotList().contains(realName)) {
sender.sendMessage(text("This fakeplayer is not saved", NamedTextColor.RED));
return true;
}
if (botList.loadNewBot(realName) == null) {
sender.sendMessage(text("Can't load bot, please check", NamedTextColor.RED));
} else {
sender.sendMessage(text("Successfully loaded fakeplayer: " + realName, NamedTextColor.GREEN));
}
return true;
}
@NotNull
private static String formatPlayerNameList(@NotNull List<String> list) {
if (list.isEmpty()) {
return "";
}
String string = list.toString();
return string.substring(1, string.length() - 1);
}
private boolean canCreate(CommandSender sender, @NotNull String name) {
BotList botList = BotList.INSTANCE;
if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) {
sender.sendMessage(text("This name is illegal", NamedTextColor.RED));
return false;
}
if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) {
sender.sendMessage(text("This player is in server", NamedTextColor.RED));
return false;
}
if (FakeplayerConfig.unableNames.contains(name)) {
sender.sendMessage(text("This name is not allowed", NamedTextColor.RED));
return false;
}
if (botList.bots.size() >= FakeplayerConfig.limit) {
sender.sendMessage(text("Fakeplayer limit is full", NamedTextColor.RED));
return false;
}
return true;
}
}
@@ -147,4 +147,4 @@ public record BotCreateState(String realName, String name, String skinName, Stri
return bot != null ? bot.getBukkitEntity() : null;
}
}
}
}
@@ -17,12 +17,14 @@
package org.leavesmc.leaves.bot;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.google.common.collect.Maps;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.RegionizedServer;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.minecraft.nbt.CompoundTag;
@@ -41,6 +43,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.ValueInput;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.event.entity.EntityRemoveEvent;
@@ -51,6 +54,7 @@ import org.slf4j.Logger;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class BotList {
@@ -67,6 +71,8 @@ public class BotList {
private final Map<String, ServerBot> botsByName = Maps.newHashMap();
private final Map<String, Set<String>> botsNameByWorldUuid = Maps.newHashMap();
public boolean forceShutdown = false;
public BotList(MinecraftServer server) {
this.server = server;
this.dataStorage = new BotDataStorage(server.storageSource);
@@ -96,7 +102,12 @@ public class BotList {
}
public ServerBot loadNewBot(String realName) {
return this.loadNewBot(realName, this.dataStorage);
try {
return this.loadNewBot(realName, this.dataStorage);
} catch (Exception e) {
LOGGER.error("Failed to load bot {}", realName, e);
return null;
}
}
public ServerBot loadNewBot(String realName, IPlayerDataStorage playerIO) {
@@ -124,7 +135,7 @@ public class BotList {
ResourceKey<Level> resourcekey = null;
if (nbt.getLong("WorldUUIDMost").isPresent() && nbt.getLong("WorldUUIDLeast").isPresent()) {
org.bukkit.World bWorld = Bukkit.getServer().getWorld(new UUID(nbt.getLong("WorldUUIDMost").orElseThrow(), nbt.getLong("WorldUUIDLeast").orElseThrow()));
World bWorld = Bukkit.getServer().getWorld(new UUID(nbt.getLong("WorldUUIDMost").orElseThrow(), nbt.getLong("WorldUUIDLeast").orElseThrow()));
if (bWorld != null) {
resourcekey = ((CraftWorld) bWorld).getHandle().dimension();
}
@@ -162,11 +173,24 @@ public class BotList {
this.botsByUUID.put(bot.getUUID(), bot);
bot.supressTrackerForLogin = true;
world.addNewPlayer(bot);
if (TickThread.isTickThreadFor(world, net.minecraft.util.Mth.floor(location.getX()) >> 4, net.minecraft.util.Mth.floor(location.getZ()) >> 4)) {
summonBot(bot, world);
} else {
RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
world, net.minecraft.util.Mth.floor(location.getX()) >> 4, net.minecraft.util.Mth.floor(location.getZ()) >> 4,
() -> summonBot(bot, world),
ca.spottedleaf.concurrentutil.util.Priority.HIGHER);
}
optional.ifPresent(nbt -> {
bot.loadAndSpawnEnderPearls(nbt);
bot.loadAndSpawnParentVehicle(nbt);
});
return bot;
}
private ServerBot summonBot(ServerBot bot, ServerLevel world) {
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);
@@ -189,6 +213,18 @@ public class BotList {
return bot;
}
/*
* return true if async
*/
public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean saved, boolean async) {
if (async && !TickThread.isTickThreadFor(bot.level(), bot.getX(), bot.getZ())) {
bot.getBukkitEntity().taskScheduler.schedule((Entity unused) -> this.removeBot(bot, reason, remover, saved), null, 1L);
return true;
}
this.removeBot(bot, reason, remover, saved);
return false;
}
public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean saved) {
return this.removeBot(bot, reason, remover, saved, this.dataStorage);
}
@@ -198,7 +234,7 @@ public class BotList {
this.server.server.getPluginManager().callEvent(event);
if (event.isCancelled() && event.getReason() != BotRemoveEvent.RemoveReason.INTERNAL) {
return true;
return false;
}
if (bot.removeTaskId != -1) {
@@ -220,7 +256,7 @@ public class BotList {
if (entity.hasExactlyOnePlayerPassenger()) {
bot.stopRiding();
entity.getPassengersAndSelf().forEach((entity1) -> {
if (!false && entity1 instanceof AbstractVillager villager) {
if (entity1 instanceof AbstractVillager villager) {
final Player human = villager.getTradingPlayer();
if (human != null) {
villager.setTradingPlayer(null);
@@ -240,18 +276,7 @@ public class BotList {
}
}
ServerLevel level = bot.level();
int chunkX = bot.getBlockX() >> 4;
int chunkZ = bot.getBlockZ() >> 4;
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(level, chunkX, chunkZ)) {
level.removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
} else {
io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
level, chunkX, chunkZ, () -> {
level.removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
});
}
bot.level().removePlayerImmediately(bot, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
this.bots.remove(bot);
this.botsByName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
@@ -285,11 +310,40 @@ public class BotList {
}
}
public void removeAll() {
public boolean removeAll() {
boolean finished = true;
AtomicInteger check = new AtomicInteger();
AtomicInteger received = new AtomicInteger();
for (ServerBot bot : this.bots) {
bot.resume = FakeplayerConfig.canResident;
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident);
if (TickThread.isTickThreadFor(bot.level(), bot.getX(), bot.getZ())) {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident);
} else {
finished = false;
check.getAndIncrement();
this.removeBot(bot, check, received, new AtomicInteger());
}
}
return finished;
}
private void removeBot(ServerBot bot, AtomicInteger check, AtomicInteger received, AtomicInteger counter) {
bot.getBukkitEntity().taskScheduler.schedule((Entity unused) -> {
if (counter.get() >= 20) {
BotList.LOGGER.info("Try to remove bot {} located in [{}]{},{},{} too many times!", bot.getName().getString(), bot.level().serverLevelData.getLevelName(), bot.getX(), bot.getY(), bot.getZ());
}
counter.getAndIncrement();
try {
this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, FakeplayerConfig.canResident);
received.getAndIncrement();
} catch (Exception e) {
this.removeBot(bot, check, received, counter);
}
if (received.get() >= check.get()) {
this.forceShutdown = true;
MinecraftServer.getServer().stopServer();
}
}, null, 1L);
}
public void loadBotInfo() {
@@ -68,6 +68,6 @@ public class BotRecipeBook extends ServerRecipeBook {
@Override
public @NotNull Packed pack() {
return new ServerRecipeBook.Packed(this.bookSettings.copy(), List.of(), List.of());
return new Packed(this.bookSettings.copy(), List.of(), List.of());
}
}
@@ -69,10 +69,10 @@ import org.bukkit.command.CommandSender;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.agent.AbstractBotConfig;
import org.leavesmc.leaves.bot.agent.Actions;
import org.leavesmc.leaves.bot.agent.Configs;
import org.leavesmc.leaves.bot.agent.actions.ServerBotAction;
import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction;
import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig;
import org.leavesmc.leaves.entity.bot.CraftBot;
import org.leavesmc.leaves.event.bot.*;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
@@ -84,9 +84,9 @@ import java.util.function.Predicate;
public class ServerBot extends ServerPlayer {
private final List<ServerBotAction<?>> actions;
private final Map<Configs<?>, AbstractBotConfig<?>> configs;
private static final Logger LOGGER = LogUtils.getLogger();
private final List<AbstractBotAction<?>> actions;
private final Map<String, AbstractBotConfig<?, ?, ?>> configs;
private static final Logger LOGGER = LogUtils.getClassLogger();
public boolean resume = false;
public BotCreateState createState;
@@ -108,9 +108,9 @@ public class ServerBot extends ServerPlayer {
this.gameMode = new ServerBotGameMode(this);
this.actions = new ArrayList<>();
ImmutableMap.Builder<Configs<?>, AbstractBotConfig<?>> configBuilder = ImmutableMap.builder();
for (Configs<?> config : Configs.getConfigs()) {
configBuilder.put(config, config.createConfig(this));
ImmutableMap.Builder<String, AbstractBotConfig<?, ?, ?>> configBuilder = ImmutableMap.builder();
for (AbstractBotConfig<?, ?, ?> config : Configs.getConfigs()) {
configBuilder.put(config.getName(), config.create().setBot(this));
}
this.configs = configBuilder.build();
@@ -154,7 +154,7 @@ public class ServerBot extends ServerPlayer {
this.notSleepTicks++;
}
if (FakeplayerConfig.regenAmount > 0.0 && getServer().getTickCount() % 20 == 0) {
if (FakeplayerConfig.regenAmount > 0.0 && this.tickCount % 20 == 0) {
float regenAmount = (float) (FakeplayerConfig.regenAmount * 20);
this.setHealth(Math.min(this.getHealth() + regenAmount, this.getMaxHealth()));
}
@@ -297,7 +297,7 @@ public class ServerBot extends ServerPlayer {
return this;
} else {
this.isChangingDimension = true;
fromLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
fromLevel.removePlayerImmediately(this, RemovalReason.CHANGED_DIMENSION);
this.unsetRemoved();
this.setServerLevel(toLevel);
this.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives());
@@ -389,14 +389,14 @@ public class ServerBot extends ServerPlayer {
if (!this.actions.isEmpty()) {
ValueOutput.TypedOutputList<CompoundTag> actionNbt = nbt.list("actions", CompoundTag.CODEC);
for (ServerBotAction<?> action : this.actions) {
for (AbstractBotAction<?> action : this.actions) {
actionNbt.add(action.save(new CompoundTag()));
}
}
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()));
}
}
@@ -429,9 +429,9 @@ public class ServerBot extends ServerPlayer {
if (nbt.list("actions", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> actionNbt = nbt.list("actions", CompoundTag.CODEC).orElseThrow();
actionNbt.forEach(actionTag -> {
ServerBotAction<?> action = Actions.getForName(actionTag.getString("actionName").orElseThrow());
AbstractBotAction<?> action = Actions.getForName(actionTag.getString("actionName").orElseThrow());
if (action != null) {
ServerBotAction<?> newAction = action.create();
AbstractBotAction<?> newAction = action.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
@@ -441,9 +441,9 @@ 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) {
Configs<?> configKey = Configs.getConfig(configTag.getString("configName").orElseThrow());
if (configKey != null) {
this.configs.get(configKey).load(configTag);
AbstractBotConfig<?, ?, ?> config = Configs.getConfig(configTag.getString("configName").orElseThrow());
if (config != null) {
config.load(configTag);
}
}
}
@@ -641,11 +641,11 @@ public class ServerBot extends ServerPlayer {
private void runAction() {
if (FakeplayerConfig.canUseAction) {
this.actions.forEach(action -> action.tryTick(this));
this.actions.removeIf(ServerBotAction::isCancelled);
this.actions.removeIf(AbstractBotAction::isCancelled);
}
}
public boolean addBotAction(ServerBotAction<?> action, CommandSender sender) {
public boolean addBotAction(AbstractBotAction<?> action, CommandSender sender) {
if (!FakeplayerConfig.canUseAction) {
return false;
}
@@ -659,7 +659,7 @@ public class ServerBot extends ServerPlayer {
return true;
}
public List<ServerBotAction<?>> getBotActions() {
public List<AbstractBotAction<?>> getBotActions() {
return actions;
}
@@ -670,11 +670,15 @@ public class ServerBot extends ServerPlayer {
}
@SuppressWarnings("unchecked")
public <E> AbstractBotConfig<E> getConfig(Configs<E> config) {
return (AbstractBotConfig<E>) Objects.requireNonNull(this.configs.get(config));
public <O, I, E extends AbstractBotConfig<O, I, E>> AbstractBotConfig<O, I, E> getConfig(@NotNull AbstractBotConfig<O, I, E> config) {
return (AbstractBotConfig<O, I, E>) Objects.requireNonNull(this.configs.get(config.getName()));
}
public <E> E getConfigValue(Configs<E> config) {
public Collection<AbstractBotConfig<?, ?, ?>> getAllConfigs() {
return configs.values();
}
public <O, I, E extends AbstractBotConfig<O, I, E>> O getConfigValue(@NotNull AbstractBotConfig<O, I, E> config) {
return this.getConfig(config).getValue();
}
@@ -1,84 +0,0 @@
/*
* 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 net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import java.util.List;
public abstract class AbstractBotConfig<E> {
private final String name;
private final CommandArgument argument;
protected ServerBot bot;
public AbstractBotConfig(String name, CommandArgument argument) {
this.name = name;
this.argument = argument;
}
public AbstractBotConfig<E> setBot(ServerBot bot) {
this.bot = bot;
return this;
}
public abstract E getValue();
public abstract void setValue(E value) throws IllegalArgumentException;
@SuppressWarnings("unchecked")
public void setFromCommand(@NotNull CommandArgumentResult result) throws IllegalArgumentException {
if (argument == CommandArgument.EMPTY) {
throw new IllegalArgumentException("No argument for " + this.getName());
}
try {
this.setValue((E) result.read(argument.getArgumentTypes().getFirst().getType()));
} catch (ClassCastException e) {
throw new IllegalArgumentException("Invalid argument type for " + this.getName() + ": " + e.getMessage());
}
}
public List<String> getMessage() {
return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + ": " + this.getValue());
}
public List<String> getChangeMessage() {
return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + " changed: " + this.getValue());
}
public String getName() {
return name;
}
public CommandArgument getArgument() {
return argument;
}
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
nbt.putString("configName", this.name);
return nbt;
}
public abstract void load(@NotNull CompoundTag nbt);
}
@@ -30,10 +30,10 @@ import java.util.Set;
public class Actions {
private static final Map<String, ServerBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, ServerBotAction<?>> actionsByClass = new HashMap<>();
private static final Map<String, AbstractBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, AbstractBotAction<?>> actionsByClass = new HashMap<>();
public static void registerAll() {
static {
register(new ServerAttackAction(), AttackAction.class);
register(new ServerBreakBlockAction(), BreakBlockAction.class);
register(new ServerDropAction(), DropAction.class);
@@ -55,7 +55,7 @@ public class Actions {
register(new ServerSwapAction(), SwapAction.class);
}
public static boolean register(@NotNull ServerBotAction<?> action, Class<? extends BotAction<?>> type) {
public static boolean register(@NotNull AbstractBotAction<?> action, Class<?> type) {
if (!actionsByName.containsKey(action.getName())) {
actionsByName.put(action.getName(), action);
actionsByClass.put(type, action);
@@ -64,14 +64,22 @@ public class Actions {
return false;
}
public static boolean register(@NotNull AbstractBotAction<?> action) {
return register(action, action.getClass());
}
public static boolean unregister(@NotNull String name) {
// TODO add in custom action api
return true;
AbstractBotAction<?> action = actionsByName.remove(name);
if (action != null) {
actionsByClass.remove(action.getClass());
return true;
}
return false;
}
@NotNull
@Contract(pure = true)
public static Collection<ServerBotAction<?>> getAll() {
public static Collection<AbstractBotAction<?>> getAll() {
return actionsByName.values();
}
@@ -81,12 +89,12 @@ public class Actions {
}
@Nullable
public static ServerBotAction<?> getForName(String name) {
public static AbstractBotAction<?> getForName(String name) {
return actionsByName.get(name);
}
@Nullable
public static ServerBotAction<?> getForClass(@NotNull Class<?> type) {
public static AbstractBotAction<?> getForClass(@NotNull Class<?> type) {
return actionsByClass.get(type);
}
}
@@ -20,63 +20,40 @@ 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.function.Supplier;
@SuppressWarnings("unused")
public class Configs<E> {
@SuppressWarnings({"unused"})
public class Configs {
private static final Map<Class<?>, AbstractBotConfig<?, ?, ?>> configs = new HashMap<>();
private static final Map<String, Configs<?>> configs = new HashMap<>();
public static final Configs<Boolean> SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new);
public static final Configs<Boolean> ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new);
public static final Configs<Boolean> SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new);
public static final Configs<Integer> SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new);
public static final Configs<ServerBot.TickType> TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new);
public static final Configs<Boolean> ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new);
private final Class<? extends AbstractBotConfig<E>> configClass;
private final Supplier<? extends AbstractBotConfig<E>> configCreator;
private Configs(Class<? extends AbstractBotConfig<E>> configClass, Supplier<? extends AbstractBotConfig<E>> configCreator) {
this.configClass = configClass;
this.configCreator = configCreator;
}
public Class<? extends AbstractBotConfig<E>> getConfigClass() {
return configClass;
}
public AbstractBotConfig<E> createConfig(ServerBot bot) {
return configCreator.get().setBot(bot);
}
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());
@Nullable
public static Configs<?> getConfig(String name) {
return configs.get(name);
public static AbstractBotConfig<?, ?, ?> getConfig(String name) {
return configs.values().stream()
.filter(config -> config.getName().equals(name))
.findFirst()
.orElse(null);
}
@NotNull
@Contract(pure = true)
public static Collection<Configs<?>> getConfigs() {
public static Collection<AbstractBotConfig<?, ?, ?>> getConfigs() {
return configs.values();
}
@NotNull
@Contract(pure = true)
public static Collection<String> getConfigNames() {
return configs.keySet();
}
@NotNull
private static <E> Configs<E> register(Class<? extends AbstractBotConfig<E>> configClass, Supplier<? extends AbstractBotConfig<E>> configCreator) {
Configs<E> config = new Configs<>(configClass, configCreator);
configs.put(config.createConfig(null).getName(), config);
return config;
@SuppressWarnings("unchecked")
private static <Value, Type, E extends AbstractBotConfig<Value, Type, E>> @NotNull E register(AbstractBotConfig<Value, Type, E> instance) {
configs.put(instance.getClass(), instance);
return (E) instance;
}
}
@@ -17,34 +17,33 @@
package org.leavesmc.leaves.bot.agent.actions;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.logging.LogUtils;
import net.minecraft.core.UUIDUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.WrappedArgument;
import org.leavesmc.leaves.event.bot.BotActionExecuteEvent;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.util.UpdateSuppressionException;
import org.slf4j.Logger;
import java.util.List;
import java.util.UUID;
import java.util.function.BiFunction;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class ServerBotAction<E extends ServerBotAction<E>> {
public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
private final String name;
private final CommandArgument argument;
private final Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments;
private final Supplier<E> creator;
private UUID uuid;
private int currentFork = 0;
private int initialTickDelay;
private int initialTickInterval;
@@ -57,13 +56,13 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
private Consumer<E> onFail;
private Consumer<E> onSuccess;
private Consumer<E> onStop;
private static final Logger LOGGER = LogUtils.getLogger();
private static final Logger LOGGER = LogUtils.getClassLogger();
public ServerBotAction(String name, CommandArgument argument, Supplier<E> creator) {
public AbstractBotAction(String name, Supplier<E> creator) {
this.name = name;
this.argument = argument;
this.uuid = UUID.randomUUID();
this.creator = creator;
this.arguments = new HashMap<>();
this.cancel = false;
this.setStartDelayTick(0);
@@ -75,12 +74,40 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
public abstract Object asCraft();
public void provideActionData(@NotNull ActionData data) {
}
public String getActionDataString() {
ActionData data = new ActionData(new ArrayList<>());
provideActionData(data);
return data.raw.stream()
.map(pair -> pair.getLeft() + "=" + pair.getRight())
.reduce((a, b) -> a + ", " + b)
.orElse("No arguments");
}
public void init() {
this.tickToNext = initialTickDelay;
this.numberRemaining = this.getDoNumber();
this.setCancelled(false);
}
public void fork(int fork) {
currentFork = fork;
}
public <T> WrappedArgument<T> addArgument(String name, ArgumentType<T> type) {
WrappedArgument<T> argument = new WrappedArgument<>(name, type);
this.arguments
.computeIfAbsent(currentFork, k -> new ArrayList<>())
.add(Pair.of(name, argument));
return argument;
}
public Map<Integer, List<Pair<String, WrappedArgument<?>>>> getArguments() {
return this.arguments;
}
public void tryTick(ServerBot bot) {
if (this.numberRemaining == 0) {
this.stop(bot, BotActionStopEvent.Reason.DONE);
@@ -168,19 +195,8 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
}
}
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
}
public void setSuggestion(int n, BiFunction<CommandSender, String, Pair<List<String>, String>> suggestion) {
this.argument.setSuggestion(n, suggestion);
}
public void setSuggestion(int n, Pair<List<String>, String> suggestion) {
this.setSuggestion(n, (sender, arg) -> suggestion);
}
public void setSuggestion(int n, List<String> tabComplete) {
this.setSuggestion(n, Pair.of(tabComplete, null));
@SuppressWarnings("RedundantThrows")
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
}
@NotNull
@@ -188,10 +204,6 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
return this.creator.get();
}
public CommandArgument getArgument() {
return this.argument;
}
public String getName() {
return this.name;
}
@@ -251,4 +263,12 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
public void setOnStop(Consumer<E> onStop) {
this.onStop = onStop;
}
public record ActionData(
List<Pair<String, String>> raw
) {
public void add(String key, String value) {
raw.add(Pair.of(key, value));
}
}
}
@@ -17,14 +17,12 @@
package org.leavesmc.leaves.bot.agent.actions;
import org.leavesmc.leaves.command.CommandArgument;
import java.util.function.Supplier;
public abstract class ServerStateBotAction<E extends ServerStateBotAction<E>> extends ServerBotAction<E> {
public abstract class AbstractStateBotAction<E extends AbstractStateBotAction<E>> extends AbstractBotAction<E> {
public ServerStateBotAction(String name, CommandArgument argument, Supplier<E> creator) {
super(name, argument, creator);
public AbstractStateBotAction(String name, Supplier<E> creator) {
super(name, creator);
this.setDoNumber(-1);
}
}
@@ -0,0 +1,59 @@
/*
* 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.actions;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;
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) {
super(name, creator);
this.addArgument("delay", integer(0))
.suggests(strings("0", "5", "10", "20"))
.setOptional(true);
this.addArgument("interval", integer(0))
.suggests(strings("20", "0", "5", "10"))
.setOptional(true);
this.addArgument("do_number", integer(-1))
.suggests(((context, builder) -> builder.suggest("-1", Component.literal("do infinite times"))))
.setOptional(true);
}
@Override
public void loadCommand(@NotNull CommandContext context) {
this.setStartDelayTick(context.getIntegerOrDefault("delay", 0));
this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20));
this.setDoNumber(context.getIntegerOrDefault("do_number", 1));
}
@Override
public void provideActionData(@NotNull ActionData data) {
super.provideActionData(data);
data.add("delay", String.valueOf(this.getStartDelayTick()));
data.add("interval", String.valueOf(this.getDoIntervalTick()));
data.add("do_number", String.valueOf(this.getDoNumber()));
data.add("remaining_do_number", String.valueOf(this.getDoNumberRemaining()));
}
}
@@ -18,33 +18,37 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
import java.util.function.Supplier;
public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extends ServerTimerBotAction<T> {
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> extends AbstractTimerBotAction<T> {
private int useTickTimeout = -1;
private int alreadyUsedTick = 0;
private int useItemRemainingTicks = 0;
public ServerUseBotAction(String name, Supplier<T> supplier) {
super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), supplier);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTickTimeout]"));
public AbstractUseBotAction(String name, Supplier<T> supplier) {
super(name, supplier);
this.addArgument("use_timeout", integer(-1))
.suggests((context, builder) -> {
builder.suggest("-1", Component.literal("no use timeout"));
builder.suggest("3", Component.literal("minimum bow shoot time"));
builder.suggest("10", Component.literal("minimum trident shoot time"));
})
.setOptional(true);
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTickTimeout = result.readInt(-1);
public void loadCommand(@NotNull CommandContext context) {
super.loadCommand(context);
this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1);
}
@Override
@@ -110,6 +114,13 @@ public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extend
this.alreadyUsedTick++;
}
@Override
public void provideActionData(@NotNull ActionData data) {
super.provideActionData(data);
data.add("use_timeout", String.valueOf(this.useTickTimeout));
data.add("already_used_tick", String.valueOf(this.alreadyUsedTick));
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction;
public class ServerAttackAction extends ServerTimerBotAction<ServerAttackAction> {
public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackAction> {
public ServerAttackAction() {
super("attack", ServerAttackAction::new);
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction;
public class ServerBreakBlockAction extends ServerTimerBotAction<ServerBreakBlockAction> {
public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBlockAction> {
public ServerBreakBlockAction() {
super("break", ServerBreakBlockAction::new);
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftDropAction;
public class ServerDropAction extends ServerTimerBotAction<ServerDropAction> {
public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
public ServerDropAction() {
super("drop", ServerDropAction::new);
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftFishAction;
public class ServerFishAction extends ServerTimerBotAction<ServerFishAction> {
public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
public ServerFishAction() {
super("fish", ServerFishAction::new);
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction;
public class ServerJumpAction extends ServerTimerBotAction<ServerJumpAction> {
public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
public ServerJumpAction() {
super("jump", ServerJumpAction::new);
@@ -17,40 +17,61 @@
package org.leavesmc.leaves.bot.agent.actions;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.coordinates.Coordinates;
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
import net.minecraft.commands.arguments.selector.EntitySelector;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.entity.Player;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftLookAction;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class ServerLookAction extends ServerBotAction<ServerLookAction> {
public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
private static final Vector ZERO_VECTOR = new Vector(0, 0, 0);
private static final DecimalFormat DF = new DecimalFormat("0.0");
private Vector pos = ZERO_VECTOR;
private ServerPlayer target = null;
public ServerLookAction() {
super("look", CommandArgument.of(CommandArgumentType.STRING, CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE), ServerLookAction::new);
this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ?
Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of(DF.format(player.getX()))).toList(), "<Player>|<X>") :
Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of("0")).toList(), "<Player>|<X>")
);
this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getY())), "<Y>") : Pair.of(List.of("0"), "<Y>"));
this.setSuggestion(2, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getZ())), "<Z>") : Pair.of(List.of("0"), "<Z>"));
super("look", ServerLookAction::new);
declarePlayerBranch();
declareLocationBranch();
}
private void declarePlayerBranch() {
this.fork(0);
this.addArgument("player", EntityArgument.player())
.setOptional(true);
}
private void declareLocationBranch() {
this.fork(1);
this.addArgument("location", Vec3Argument.vec3(false));
}
@Override
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
EntitySelector selector = context.getArgumentOrDefault("player", EntitySelector.class, null);
Coordinates location = context.getArgumentOrDefault("location", Coordinates.class, null);
CommandSourceStack source = context.getSource();
if (selector == null && location == null) {
Entity sender = source.getEntityOrException();
this.setPos(new Vector(sender.getX(), sender.getY(), sender.getZ()));
} else if (selector != null) {
ServerPlayer player = selector.findSinglePlayer(source);
this.setTarget(player);
} else {
Vec3 vector = location.getPosition(source);
this.setPos(new Vector(vector.x, vector.y, vector.z));
}
}
@Override
@@ -94,6 +115,16 @@ public class ServerLookAction extends ServerBotAction<ServerLookAction> {
return target;
}
@Override
public void provideActionData(@NotNull ActionData data) {
super.provideActionData(data);
if (target != null) {
data.add("target", target.getName().getString());
} else {
data.add("position", String.format("(%.2f, %.2f, %.2f)", pos.getX(), pos.getY(), pos.getZ()));
}
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
if (target != null) {
@@ -104,22 +135,6 @@ public class ServerLookAction extends ServerBotAction<ServerLookAction> {
return true;
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
String nameOrX = result.readString(player.getScoreboardName());
ServerPlayer player1 = player.getServer().getPlayerList().getPlayerByName(nameOrX);
if (player1 != null) {
this.setTarget(player1);
return;
}
try {
Vector vector = result.readVectorYZ(Double.parseDouble(nameOrX));
this.setPos(vector);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid vector");
}
}
@Override
public Object asCraft() {
return new CraftLookAction(this);
@@ -23,16 +23,15 @@ import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftMountAction;
import java.util.Comparator;
import java.util.List;
public class ServerMountAction extends ServerBotAction<ServerMountAction> {
public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
public ServerMountAction() {
super("mount", CommandArgument.EMPTY, ServerMountAction::new);
super("mount", ServerMountAction::new);
}
@Override
@@ -40,8 +39,8 @@ public class ServerMountAction extends ServerBotAction<ServerMountAction> {
Location center = bot.getBukkitEntity().getLocation();
List<Vehicle> vehicles = center.getNearbyEntitiesByType(
Vehicle.class,
3,
vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 2
4,
vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 3
).stream().sorted(Comparator.comparingDouble(
(vehicle) -> center.distanceSquared(vehicle.getLocation())
)).toList();
@@ -17,39 +17,46 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection;
import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
import static java.util.stream.Collectors.toMap;
import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings;
private static final Pair<List<String>, String> suggestions = Pair.of(
Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList(),
"<Direction>"
);
public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
private static final Map<String, MoveDirection> NAME_TO_DIRECTION = Arrays.stream(MoveDirection.values()).collect(toMap(
it -> it.name,
it -> it
));
private MoveDirection direction = MoveDirection.FORWARD;
public ServerMoveAction() {
super("move", CommandArgument.of(CommandArgumentType.ofEnum(MoveDirection.class)), ServerMoveAction::new);
this.setSuggestion(0, suggestions);
super("move", ServerMoveAction::new);
this.addArgument("direction", StringArgumentType.word())
.suggests(strings(
Arrays.stream(MoveDirection.values())
.map((it) -> it.name)
.toList()
));
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
this.direction = result.read(MoveDirection.class);
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
String raw = context.getArgument("direction", String.class);
MoveDirection direction = NAME_TO_DIRECTION.get(raw);
if (direction == null) {
throw new IllegalArgumentException("Invalid direction");
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
}
this.direction = direction;
}
@Override
@@ -74,6 +81,12 @@ public class ServerMoveAction extends ServerStateBotAction<ServerMoveAction> {
return true;
}
@Override
public void provideActionData(@NotNull ActionData data) {
super.provideActionData(data);
data.add("direction", direction.name);
}
public MoveDirection getDirection() {
return direction;
}
@@ -17,42 +17,44 @@
package org.leavesmc.leaves.bot.agent.actions;
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.entity.Player;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Objects;
public class ServerRotationAction extends ServerBotAction<ServerRotationAction> {
public class ServerRotationAction extends AbstractBotAction<ServerRotationAction> {
private static final DecimalFormat DF = new DecimalFormat("0.00");
public ServerRotationAction() {
super("rotation", CommandArgument.of(CommandArgumentType.FLOAT, CommandArgumentType.FLOAT), ServerRotationAction::new);
this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getYaw())), "[yaw]") : Pair.of(List.of("0"), "<yaw>"));
this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getPitch())), "[pitch]") : Pair.of(List.of("0"), "<pitch>"));
super("rotation", ServerRotationAction::new);
this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180))
.suggests((context, builder) -> builder.suggest(
DF.format(context.getSource().getEntityOrException().getYRot()),
Component.literal("current player yaw")
))
.setOptional(true);
this.addArgument("pitch", FloatArgumentType.floatArg(-90, 90))
.suggests((context, builder) -> builder.suggest(
DF.format(context.getSource().getEntityOrException().getXRot()),
Component.literal("current player pitch")
))
.setOptional(true);
}
private float yaw = 0.0f;
private float pitch = 0.0f;
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
try {
this.yaw = result.readFloat(Objects.requireNonNull(player).getYRot());
this.pitch = result.readFloat(player.getXRot());
} catch (Exception e) {
throw new IllegalArgumentException("No valid rotation specified", e);
}
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
this.yaw = context.getFloatOrDefault("yaw", context.getSource().getEntityOrException().getYRot());
this.pitch = context.getFloatOrDefault("pitch", context.getSource().getEntityOrException().getXRot());
}
public void setYaw(float yaw) {
@@ -71,6 +73,13 @@ public class ServerRotationAction extends ServerBotAction<ServerRotationAction>
return this.pitch;
}
@Override
public void provideActionData(@NotNull ActionData data) {
super.provideActionData(data);
data.add("yaw", DF.format(this.yaw));
data.add("pitch", DF.format(this.pitch));
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
@@ -19,14 +19,13 @@ package org.leavesmc.leaves.bot.agent.actions;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
public class ServerSneakAction extends ServerStateBotAction<ServerSneakAction> {
public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction> {
public ServerSneakAction() {
super("sneak", CommandArgument.EMPTY, ServerSneakAction::new);
super("sneak", ServerSneakAction::new);
}
@Override
@@ -21,13 +21,12 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction;
public class ServerSwapAction extends ServerBotAction<ServerSwapAction> {
public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
public ServerSwapAction() {
super("swap", CommandArgument.EMPTY, ServerSwapAction::new);
super("swap", ServerSwapAction::new);
}
@Override
@@ -20,13 +20,12 @@ package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction;
public class ServerSwimAction extends ServerStateBotAction<ServerSwimAction> {
public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
public ServerSwimAction() {
super("swim", CommandArgument.EMPTY, ServerSwimAction::new);
super("swim", ServerSwimAction::new);
}
@Override
@@ -1,49 +0,0 @@
/*
* 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.actions;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import java.util.List;
import java.util.function.Supplier;
public abstract class ServerTimerBotAction<E extends ServerTimerBotAction<E>> extends ServerBotAction<E> {
public ServerTimerBotAction(String name, Supplier<E> creator) {
this(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator);
}
public ServerTimerBotAction(String name, CommandArgument argument, Supplier<E> creator) {
super(name, argument, creator);
this.setSuggestion(0, Pair.of(List.of("0"), "[TickDelay]"));
this.setSuggestion(1, Pair.of(List.of("20"), "[TickInterval]"));
this.setSuggestion(2, Pair.of(List.of("1", "-1"), "[DoNumber]"));
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
this.setStartDelayTick(result.readInt(0));
this.setDoIntervalTick(result.readInt(20));
this.setDoNumber(result.readInt(1));
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction;
public class ServerUseItemAction extends ServerUseBotAction<ServerUseItemAction> {
public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemAction> {
public ServerUseItemAction() {
super("use", ServerUseItemAction::new);
@@ -34,7 +34,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
public class ServerUseItemAutoAction extends ServerUseBotAction<ServerUseItemAutoAction> {
public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemAutoAction> {
public ServerUseItemAutoAction() {
super("use_auto", ServerUseItemAutoAction::new);
@@ -24,7 +24,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
public class ServerUseItemOffhandAction extends ServerUseBotAction<ServerUseItemOffhandAction> {
public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseItemOffhandAction> {
public ServerUseItemOffhandAction() {
super("use_offhand", ServerUseItemOffhandAction::new);
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction;
public class ServerUseItemOnAction extends ServerUseBotAction<ServerUseItemOnAction> {
public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnAction> {
public ServerUseItemOnAction() {
super("use_on", ServerUseItemOnAction::new);
@@ -25,7 +25,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
public class ServerUseItemOnOffhandAction extends ServerUseBotAction<ServerUseItemOnOffhandAction> {
public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUseItemOnOffhandAction> {
public ServerUseItemOnOffhandAction() {
super("use_on_offhand", ServerUseItemOnOffhandAction::new);
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction;
public class ServerUseItemToAction extends ServerUseBotAction<ServerUseItemToAction> {
public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToAction> {
public ServerUseItemToAction() {
super("use_to", ServerUseItemToAction::new);

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