Compare commits
156 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa07ef21ca | |||
| d50ad73a17 | |||
| 0d794003bc | |||
| 3856196543 | |||
| eff43b61ff | |||
| 06514362b8 | |||
| 5b94c79f39 | |||
| 24a315a368 | |||
| 3d54e47c5e | |||
| 6aadb1ca19 | |||
| 0a4a6baf70 | |||
| ee36fab64c | |||
| e85db692f3 | |||
| 9635e516dd | |||
| d7e1b3a6bb | |||
| 0fc9a1426d | |||
| 017e49da8a | |||
| 42d870e32b | |||
| 54ff033ef6 | |||
| 9761fde77d | |||
| e0d42cb1d3 | |||
| 559b2e089a | |||
| a07649d14d | |||
| 6aa709cf75 | |||
| 6a452799cc | |||
| e17a3f2033 | |||
| 74ac0bccf5 | |||
| f65b7f176b | |||
| 97a17dbf78 | |||
| c5194eeb8f | |||
| 58c5573421 | |||
| 1907a41329 | |||
| 21cce73216 | |||
| 163a9902cc | |||
| ba1216d4d3 | |||
| beb5cbeb52 | |||
| 5cc4371833 | |||
| 35f1e58d4d | |||
| 690d7c2785 | |||
| 115c9f8ee8 | |||
| faa3529943 | |||
| 3c3a2a6ff4 | |||
| 25776c7200 | |||
| 74e9d146e3 | |||
| a8b2972e0e | |||
| ed3063a477 | |||
| 85d2fa3372 | |||
| b22e9e588b | |||
| 90b751da5a | |||
| 7efeb48a7e | |||
| e5cc20ba9b | |||
| 46e7abe59c | |||
| 40df6b9dfb | |||
| 5559fa8bcc | |||
| 6319ddf78f | |||
| e74300a756 | |||
| d9674b4e7c | |||
| 6d02f00ac0 | |||
| 2960e7d24f | |||
| d950c6d3e8 | |||
| 357c351b95 | |||
| a780b13fcc | |||
| cf80fc6a86 | |||
| 20acc9ccf5 | |||
| e49ab25111 | |||
| eed4457419 | |||
| 429a0345d9 | |||
| 670d4e39c9 | |||
| 5d4ddb9a6b | |||
| 0ad90dc36e | |||
| 284810dfb8 | |||
| 0f67f445b9 | |||
| 018cc61204 | |||
| b9c3d8deea | |||
| 0d5b289d65 | |||
| 5b20ad2e2c | |||
| 9fcce731d0 | |||
| 0783c97224 | |||
| 300e891906 | |||
| a3e0a3ee1a | |||
| b3703e2069 | |||
| d3c8da4edb | |||
| bed0bfff06 | |||
| 238231b28b | |||
| db772aaf62 | |||
| b1bee59e6c | |||
| a9d24bd32c | |||
| f299d5188d | |||
| bbcc85fa93 | |||
| c26d8d1ee3 | |||
| 7bc12d2487 | |||
| 2c3aa4b68e | |||
| 91312b7a15 | |||
| 77c412bfe8 | |||
| c06d875df7 | |||
| 5e96851513 | |||
| 91b3ad527c | |||
| 959a1c346c | |||
| b594382a6a | |||
| 37f1b4e5f1 | |||
| af2af944bf | |||
| 54688d8e34 | |||
| 7b7f0b6d1f | |||
| 0ab3983145 | |||
| 24a9d5cea8 | |||
| 8ee77c3354 | |||
| 98df254bad | |||
| 19f001ad1b | |||
| 106dfeaa38 | |||
| 403ae2b2d0 | |||
| 96c99519d5 | |||
| 5c4031b836 | |||
| 376857ff97 | |||
| fa1ab90579 | |||
| fc9c6937b6 | |||
| 12d8ba9050 | |||
| 38a1ce0443 | |||
| a5a415e495 | |||
| b7bf1b5916 | |||
| 4a8888c578 | |||
| 2c59a32afe | |||
| cc5382977d | |||
| c07dde1c0b | |||
| 871a003a2e | |||
| d6a981a6e9 | |||
| bc166a9fb6 | |||
| feebf388f8 | |||
| dbcf764e76 | |||
| 735fe8855a | |||
| 1b45a090f6 | |||
| bb1335d390 | |||
| 00743c841f | |||
| bdb9c9dec4 | |||
| ac3653dda7 | |||
| a08fd04751 | |||
| f5debe9ee1 | |||
| 1a84d2e670 | |||
| e96891275d | |||
| 9e342c6683 | |||
| 00f7f5ee2b | |||
| 77b9582c4a | |||
| 184048fd26 | |||
| 7ccca03023 | |||
| b34fa8237e | |||
| 42a4d18717 | |||
| 2d8d7f5784 | |||
| bf509bcded | |||
| ef6759a9ab | |||
| bc1483ea7a | |||
| 5768a60ba8 | |||
| 05434f422c | |||
| 21e9299352 | |||
| 83e7718346 | |||
| 5845b976c1 | |||
| 4ca94280ae | |||
| 4cc49c6d99 |
@@ -1,7 +1,7 @@
|
||||
name: Bug反馈 Bug report
|
||||
description:
|
||||
报告Bug,插件不兼容情况,以及其他相关问题。
|
||||
Report issues with plugin incompatbility or other behavior related issues.
|
||||
Report issues with plugin incompatibility or other behavior related issues.
|
||||
labels:
|
||||
- bug
|
||||
- pending
|
||||
@@ -25,7 +25,7 @@ body:
|
||||
LophineMC服务端发行版本 LophineMC server release version (contains the git commit's hash)<br>
|
||||
通过执行`/version`命令将获取到的内容复制到这里。 Run `/version` on your server and paste the full, unmodified output here.
|
||||
placeholder: >
|
||||
e.g. git-Lophine-"0635a89" (MC: 1.20.4)
|
||||
e.g. git-Lophine-"fa1ab90" (MC: 1.21.8)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -41,7 +41,7 @@ body:
|
||||
attributes:
|
||||
label: 观测到的实际行为 Observed/Actual behavior
|
||||
description: 你实际看到的。 What you actually saw.
|
||||
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
|
||||
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -65,6 +65,20 @@ body:
|
||||
To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config-file-list
|
||||
attributes:
|
||||
label: 配置文件列表(如果可以)。 Config File List (if possible).
|
||||
description:
|
||||
服务器上的配置文件列表。
|
||||
All config files on your server.
|
||||
例如以下文件(或者文件夹):
|
||||
Example files (or folders):
|
||||
- \spigot.yml
|
||||
- \bukkit.yml
|
||||
- \config\\\*
|
||||
- \lophine_config\\\*
|
||||
- \luminol_config\\\*
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
|
||||
@@ -28,7 +28,7 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: othre
|
||||
id: other
|
||||
attributes:
|
||||
label: 其他 Other
|
||||
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
|
||||
+28
-13
@@ -14,7 +14,7 @@ on:
|
||||
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"
|
||||
description: "Force disable push to repo if you enter 2, force push to repo if you enter 1, default push if not released else skip push repo"
|
||||
required: false
|
||||
default: ""
|
||||
comments:
|
||||
@@ -28,18 +28,20 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
environment: default
|
||||
env:
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
steps:
|
||||
- name: Checkout Git Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set Up JDK
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: zulu
|
||||
java-version: 21
|
||||
java-version: 25
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
@@ -51,13 +53,13 @@ jobs:
|
||||
run: ./gradlew --refresh-dependencies applyAllPatches
|
||||
|
||||
- name: Build Paperclip Jar
|
||||
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
|
||||
run: ./gradlew --refresh-dependencies createPaperclipJar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.project_id_b }} CI Artifacts
|
||||
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
|
||||
path: lophine-server/build/libs/*-paperclip-*.jar
|
||||
|
||||
- name: Set Environment
|
||||
if: github.event_name != 'pull_request'
|
||||
@@ -81,11 +83,23 @@ jobs:
|
||||
done
|
||||
echo "tag=${{ env.tag }}-${counter}" >> $GITHUB_ENV
|
||||
echo "release_count= - ${counter}" >> $GITHUB_ENV
|
||||
release_exists=false
|
||||
fi
|
||||
echo "release_exists=${release_exists}" >> $GITHUB_ENV
|
||||
|
||||
- name: Check If Branch In Expectations
|
||||
if: github.event_name != 'pull_request' && env.flag_release == 'true'
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_NAME" == ver/* ]] || [[ "$GITHUB_REF_NAME" == exp/* ]] || [[ "$GITHUB_REF_NAME" == dev/* ]]; then
|
||||
echo "Branch is in expected prefixes"
|
||||
echo "unexpect=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Branch is NOT in expected prefixes"
|
||||
echo "unexpect=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- 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
|
||||
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1'
|
||||
continue-on-error: true
|
||||
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
|
||||
env:
|
||||
@@ -93,13 +107,14 @@ jobs:
|
||||
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
|
||||
|
||||
- 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'
|
||||
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && 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
|
||||
if [ "${{ inputs.comments }}" == "" ]; then
|
||||
echo "No comments provided"
|
||||
echo "flag_comment=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "flag_comment=false" >> $GITHUB_ENV
|
||||
echo "Comments provided: ${{ inputs.comments }}"
|
||||
echo "flag_comment=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create Release - No Comment
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Qodana
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches: # Specify your branches here
|
||||
- ver/* # Stable branch
|
||||
- exp/* # Experimental branch
|
||||
- dev/* # Development Branch
|
||||
|
||||
jobs:
|
||||
qodana:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
|
||||
fetch-depth: 0 # a full history is required for pull request analysis
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@latest
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1658551725 }}
|
||||
QODANA_ENDPOINT: 'https://qodana.cloud'
|
||||
+2
-4
@@ -6,12 +6,10 @@ build
|
||||
|
||||
/run
|
||||
|
||||
/lightingluminol-server/build.gradle.kts
|
||||
/lightingluminol-api/build.gradle.kts
|
||||
/luminol-server/build.gradle.kts
|
||||
/lophine-server/build.gradle.kts
|
||||
/lophine-api/build.gradle.kts
|
||||
/luminol-server/src/minecraft
|
||||
/paper-server
|
||||
/luminol-api/build.gradle.kts
|
||||
/paper-api
|
||||
/paper-api-generator
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package fun.bm.lophine.config.modules.experiment;
|
||||
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||
import me.earthme.luminol.config.flags.TransformedConfig;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
/*
|
||||
* This is a config module for redstone in experimental level
|
||||
* If we think configs from here is stable for future, we will move them to function module directory
|
||||
*/
|
||||
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
|
||||
public class RedStoneConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "redstone-ignore-upwards-update", comments = """
|
||||
Should the pre-1.20 mechanism be reintroduced:
|
||||
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
|
||||
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters, and redstone comparators do not check for attachment when receiving status updates from below""")
|
||||
public static boolean redstoneIgnoreUpwardsUpdate = false;
|
||||
|
||||
@ConfigInfo(name = "cce-update-suppression", comments = """
|
||||
Is it permissible to use ClassCastException for update suppression?""")
|
||||
public static boolean cce = false;
|
||||
|
||||
@HotReloadUnsupported
|
||||
@ConfigInfo(name = "instant-block-updater")
|
||||
public static boolean instantBlockUpdater = false;
|
||||
|
||||
@ConfigInfo(name = "old-block-remove-behaviour")
|
||||
public static boolean oldBlockRemoveBehaviour = false;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package fun.bm.lophine.config.modules.fixes;
|
||||
|
||||
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.FIXES, name = "update-suppression-crash-fix")
|
||||
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "enabled", comments = """
|
||||
Should crash caused by update suppression be prevented?""")
|
||||
public static boolean enabled = true;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sun, 22 Mar 2026 01:39:17 +0800
|
||||
Subject: [PATCH] Carpet features
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index f5fb4e210c07f32e52eb8c1ba166d1571a6778c7..e990c147e1b632ef5a33e4f3c37b5cd608040ac7 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -25,6 +25,13 @@ public class ConfigManager {
|
||||
public static void initConfigs() {
|
||||
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
|
||||
+ configfiles.put("lophine_carpet", ConfigsInstance.of(
|
||||
+ new java.io.File("lophine_config"),
|
||||
+ "lophine_carpet",
|
||||
+ "lophine_carpet_config.toml",
|
||||
+ "lophinecarpetconfig",
|
||||
+ "fun.bm.lophine.carpet.config.modules"
|
||||
+ )); // add lophine carpet config
|
||||
preLoad();
|
||||
}
|
||||
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sat, 7 Feb 2026 23:57:50 +0800
|
||||
Subject: [PATCH] Leaves: Catch update suppression crash
|
||||
|
||||
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/network/PacketProcessor.java b/net/minecraft/network/PacketProcessor.java
|
||||
index cf162ec136309d05c5aa03042652ab3932935917..469ffd54eb5af980f49061bbec0a72f4e888f8a3 100644
|
||||
--- a/net/minecraft/network/PacketProcessor.java
|
||||
+++ b/net/minecraft/network/PacketProcessor.java
|
||||
@@ -107,7 +107,20 @@ public class PacketProcessor implements AutoCloseable {
|
||||
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(ListenerAndPacket.this.packet.getClass().getName()))); try { // Folia - profiler
|
||||
this.packet.handle(this.listener);
|
||||
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
|
||||
- } catch (Exception var3) {
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
|
||||
+ exception.providePlayer(gamePacketListener.player);
|
||||
+ }
|
||||
+ exception.consume();
|
||||
+ } catch (Exception var3) {
|
||||
+ if (var3.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
|
||||
+ exception.providePlayer(gamePacketListener.player);
|
||||
+ }
|
||||
+ exception.consume();
|
||||
+ }
|
||||
+ // Leaves end - update suppression crash fix
|
||||
if (var3 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) {
|
||||
throw PacketUtils.makeReportedException(var3, this.packet, this.listener);
|
||||
}
|
||||
diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java
|
||||
index ab80a66646a7ebe2862221ac342b06c14fcfc734..7834f3da4d0ff4a5cdec46b023d7348369a12e96 100644
|
||||
--- a/net/minecraft/network/protocol/PacketUtils.java
|
||||
+++ b/net/minecraft/network/protocol/PacketUtils.java
|
||||
@@ -34,6 +34,7 @@ public class PacketUtils {
|
||||
}
|
||||
|
||||
public static <T extends PacketListener> ReportedException makeReportedException(Exception exception, Packet<T> packet, T packetListener) {
|
||||
+
|
||||
if (exception instanceof ReportedException reportedException) {
|
||||
fillCrashReport(reportedException.getReport(), packetListener, packet);
|
||||
return reportedException;
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 24f83a6875219aaf4b29e2461afcd0478a391014..9457d86461b032ff2dac338620c3d4a54e6c7071 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1978,11 +1978,27 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
try {
|
||||
profiler.startTimer(serverLevel.tickTimerId); try { // Folia - profiler
|
||||
serverLevel.tick(hasTimeLeft, region); // Folia - region threading
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ exception.provideLevel(serverLevel);
|
||||
+ exception.consume();
|
||||
} finally { profiler.stopTimer(serverLevel.tickTimerId); } // Folia - profiler
|
||||
} catch (Throwable var7) {
|
||||
- CrashReport crashReport = CrashReport.forThrowable(var7, "Exception ticking world");
|
||||
- serverLevel.fillReportDetails(crashReport);
|
||||
- throw new ReportedException(crashReport);
|
||||
+ org.leavesmc.leaves.util.UpdateSuppressionException updateSuppressionException = null;
|
||||
+ if (var7 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ updateSuppressionException = exception;
|
||||
+ } else if (var7.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ updateSuppressionException = exception;
|
||||
+ }
|
||||
+ if (updateSuppressionException != null) {
|
||||
+ updateSuppressionException.provideLevel(serverLevel);
|
||||
+ updateSuppressionException.consume();
|
||||
+ } else {
|
||||
+ // Leaves end - update suppression crash fix
|
||||
+ CrashReport crashReport = CrashReport.forThrowable(var7, "Exception ticking world");
|
||||
+ serverLevel.fillReportDetails(crashReport);
|
||||
+ throw new ReportedException(crashReport);
|
||||
+ }
|
||||
}
|
||||
|
||||
profilerFiller.pop();
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 9345bdb2770e7c27488c547012020337fc651edc..447b3e6149716a3ca4b9721746ea471c94c56e67 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -894,7 +894,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Kaiiju end
|
||||
|
||||
profilerFiller.push("tick");
|
||||
- this.guardEntityTick(this::tickNonPassenger, entity);
|
||||
+ // Lophine start - update suppression crash fix
|
||||
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
+ try {
|
||||
+ this.guardEntityTick(this::tickNonPassenger, entity); // Lophine changed
|
||||
+ // Leaves start - update suppression crash fix - for dragon dupe
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ exception.provideLevel(this);
|
||||
+ exception.consume();
|
||||
+ // Leaves end - update suppression crash fix - for dragon dupe
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.guardEntityTick(this::tickNonPassenger, entity);
|
||||
+ }
|
||||
+ // Lophine end - update suppression crash fix
|
||||
profilerFiller.pop();
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index ca751564d9189e873d4a53be9a2c68b2a04a8624..e6ec0788b88d3431c06134c879b4bae9c769dac1 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1108,6 +1108,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
|
||||
// Folia - region threading - move to main tick loop where we can detect duplicates
|
||||
// CraftBukkit end
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ exception.providePlayer(this);
|
||||
+ exception.provideLevel(this.level());
|
||||
+ exception.consume();
|
||||
+ // Leaves start - update suppression crash fix
|
||||
} catch (Throwable var4) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked");
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 5ac53fcdca5fa6aae0452840e78d67653ceececb..26de0d418e0dcbb4ecd88630d75c677fdc7ff93d 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1427,9 +1427,19 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
|
||||
this.walkingStepSound(pos, state);
|
||||
}
|
||||
|
||||
+ // Leaves start - update suppression crash fix
|
||||
if (broadcastGameEvent) {
|
||||
- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, state));
|
||||
+ try {
|
||||
+ this.level().gameEvent(net.minecraft.world.level.gameevent.GameEvent.STEP, this.position(), net.minecraft.world.level.gameevent.GameEvent.Context.of(this, state));
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||
+ exception.provideBlock(level, pos, state.getBlock());
|
||||
+ if (this instanceof net.minecraft.server.level.ServerPlayer player) {
|
||||
+ exception.providePlayer(player);
|
||||
+ }
|
||||
+ exception.consume();
|
||||
+ }
|
||||
}
|
||||
+ // Leaves end - update suppression crash fix
|
||||
|
||||
return true;
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
index cb0471b06c33d1f79ba5b7a9b6036ba6b089d2be..46d6c6e3befc70a6878e12a4d75575e6d48d10ca 100644
|
||||
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
@@ -181,7 +181,17 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||
|
||||
@Override
|
||||
protected int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos, Direction direction) {
|
||||
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ try {
|
||||
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||
+ } catch (ClassCastException ex) {
|
||||
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
|
||||
+ } else {
|
||||
+ throw ex;
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - update suppression crash fix
|
||||
}
|
||||
|
||||
public static Block getBlockByColor(@Nullable DyeColor color) {
|
||||
diff --git a/net/minecraft/world/level/block/state/StateHolder.java b/net/minecraft/world/level/block/state/StateHolder.java
|
||||
index c020d1944a25e2cd247e30a97c35bf93731d694a..74967f20099ea58cea1f9fc0f2387d8c45b54748 100644
|
||||
--- a/net/minecraft/world/level/block/state/StateHolder.java
|
||||
+++ b/net/minecraft/world/level/block/state/StateHolder.java
|
||||
@@ -104,7 +104,16 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
|
||||
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
+ org.leavesmc.leaves.util.UpdateSuppressionException exception = new org.leavesmc.leaves.util.UpdateSuppressionException(null, null, null, null, iae);
|
||||
+ if (exception.getStackTrace()[1].getClassName().startsWith("net.minecraft")) {
|
||||
+ throw exception;
|
||||
+ }
|
||||
+ }
|
||||
+ throw iae;
|
||||
+ // Leaves end - update suppression crash fix
|
||||
// Paper end - optimise blockstate property access
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 77577d0df9b14a7ad55b2866c2ac31863226458b..5551d80a81c2878136f96b3e695c4888c7105a49 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -383,7 +383,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
if (blockState == state) {
|
||||
return null;
|
||||
} else {
|
||||
- Block block = state.getBlock();
|
||||
+ Block block = state.getBlock(); try { // Leaves start - update suppression crash fix
|
||||
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state);
|
||||
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state);
|
||||
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state);
|
||||
@@ -457,6 +457,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
this.markUnsaved();
|
||||
return blockState;
|
||||
}
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) { e.provideBlock(level, pos, block); throw e; } // Leaves - update suppression crash fix
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
index af21821513f11011e7bf3841d2f79cb99e4cd517..32488203ff074b675f5c8831d157b1d91bae48a9 100644
|
||||
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
@@ -63,9 +63,22 @@ public interface NeighborUpdater {
|
||||
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
|
||||
// Spigot start
|
||||
} catch (StackOverflowError ex) {
|
||||
+ // Leaves start - update suppression crash fix
|
||||
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, ex);
|
||||
+ }
|
||||
level.lastPhysicsProblem = pos.immutable();
|
||||
// Spigot end
|
||||
} catch (Throwable var9) {
|
||||
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException ue) {
|
||||
+ ue.provideBlock(level, pos, neighborBlock);
|
||||
+ throw ue;
|
||||
+ } else {
|
||||
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, var9);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - update suppression crash fix
|
||||
CrashReport crashReport = CrashReport.forThrowable(var9, "Exception while updating neighbours");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Block being updated");
|
||||
crashReportCategory.setDetail(
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sat, 15 Nov 2025 01:12:39 +0800
|
||||
Subject: [PATCH] Leaves: CCE update suppression
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
index 46d6c6e3befc70a6878e12a4d75575e6d48d10ca..77840814806c7d07b58cd716cf7ec095e894498a 100644
|
||||
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
@@ -183,7 +183,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||
protected int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos, Direction direction) {
|
||||
// Leaves start - update suppression crash fix
|
||||
try {
|
||||
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce ?
|
||||
+ AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container) level.getBlockEntity(pos)) : // Leaves - make cce happy(?)
|
||||
+ AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||
} catch (ClassCastException ex) {
|
||||
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
Date: Wed, 14 Jun 2023 12:07:07 +0800
|
||||
Subject: [PATCH] Leaves: Redstone ignore upwards update
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
|
||||
index 578e7c8dc601f53cf2a068685c6901bfaf47e763..0686aa5425c00e10beb381f3c3ff3c554603cd49 100644
|
||||
--- a/net/minecraft/world/level/block/ComparatorBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
|
||||
@@ -58,6 +58,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
|
||||
BlockState neighborState,
|
||||
RandomSource random
|
||||
) {
|
||||
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
|
||||
return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)
|
||||
? Blocks.AIR.defaultBlockState()
|
||||
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
|
||||
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index ba253a9af6141d8ea99c064e3cc0c6486c221098..48f9e234e4025633cbc41d334d88ada36c2e0d7b 100644
|
||||
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -178,7 +178,7 @@ public class RedStoneWireBlock extends Block {
|
||||
RandomSource random
|
||||
) {
|
||||
if (direction == Direction.DOWN) {
|
||||
- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state;
|
||||
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19
|
||||
} else if (direction == Direction.UP) {
|
||||
return this.getConnectionState(level, state, pos);
|
||||
} else {
|
||||
@@ -238,7 +238,7 @@ public class RedStoneWireBlock extends Block {
|
||||
BlockPos blockPos = pos.relative(direction);
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (nonNormalCubeAbove) {
|
||||
- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState);
|
||||
+ boolean flag = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19
|
||||
if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) {
|
||||
if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) {
|
||||
return RedstoneSide.UP;
|
||||
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
|
||||
index 87e1a32376adc5a15f035b62bc1f672c507cd230..26c10c1fecb976f3ef0338aa78603d454d1b3fe8 100644
|
||||
--- a/net/minecraft/world/level/block/RepeaterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
|
||||
@@ -68,6 +68,7 @@ public class RepeaterBlock extends DiodeBlock {
|
||||
BlockState neighborState,
|
||||
RandomSource random
|
||||
) {
|
||||
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
|
||||
if (direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
} else {
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 17 Nov 2025 18:41:08 +0800
|
||||
Subject: [PATCH] Instant Block Updater
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 33d186d660ce3e3dc8cf26cd521fa99291ff78a5..ce1918d12b88835ea79a5c0dc90e0315c408830b 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -494,7 +494,7 @@ public final class RegionizedWorldData {
|
||||
public long lastMidTickExecuteFailure;
|
||||
// From Level
|
||||
public boolean populating;
|
||||
- public final CollectingNeighborUpdater neighborUpdater;
|
||||
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater;
|
||||
public boolean captureBlockStates = false;
|
||||
public boolean captureTreeGeneration = false;
|
||||
public final Map<BlockPos, CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
|
||||
@@ -582,7 +582,7 @@ public final class RegionizedWorldData {
|
||||
this.world = world;
|
||||
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
|
||||
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
|
||||
- this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
|
||||
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world) : new CollectingNeighborUpdater(world, world.neighbourUpdateMax); // Lophine - Instant Block Updater
|
||||
this.nearbyPlayers = new NearbyPlayers(world);
|
||||
this.wireHandler = new alternate.current.wire.WireHandler(world);
|
||||
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 447b3e6149716a3ca4b9721746ea471c94c56e67..d8a2f8a1fbf0189e86ccbce70a84641a143cdb91 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -927,12 +927,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Paper - rewrite chunk system
|
||||
profilerFiller.pop();
|
||||
profilerFiller.push("debugSynchronizers");
|
||||
+ // Lophine start - instant neighbor updates
|
||||
+ if (regionizedWorldData.neighborUpdater instanceof net.minecraft.world.level.redstone.CollectingNeighborUpdater neighborUpdater) {
|
||||
if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) {
|
||||
- regionizedWorldData.neighborUpdater // Folia - region threading
|
||||
- .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
|
||||
+ neighborUpdater // Folia - region threading
|
||||
+ .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
|
||||
} else {
|
||||
- regionizedWorldData.neighborUpdater.setDebugListener(null); // Folia - region threading
|
||||
+ neighborUpdater.setDebugListener(null); // Folia - region threading
|
||||
}
|
||||
+ }
|
||||
+ // Lophine end - instant neighbor updates
|
||||
|
||||
this.debugSynchronizers.tick(this.server.debugSubscribers());
|
||||
profilerFiller.pop();
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 18 Nov 2025 00:24:32 +0800
|
||||
Subject: [PATCH] Revert TrapDoorBlock changes form Paper
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/TrapDoorBlock.java b/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||
index b45ae50db32c4156b8f8008335673d20c570c72d..af78831441f362b0129aa864854ce5a64d544640 100644
|
||||
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||
@@ -128,37 +128,7 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
|
||||
if (!level.isClientSide()) {
|
||||
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
|
||||
if (hasNeighborSignal != state.getValue(POWERED)) {
|
||||
- // CraftBukkit start
|
||||
- org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
- int power = bblock.getBlockPower();
|
||||
- int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
|
||||
-
|
||||
- if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
|
||||
- org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
|
||||
- level.getCraftServer().getPluginManager().callEvent(eventRedstone);
|
||||
- hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
|
||||
- }
|
||||
- // CraftBukkit end
|
||||
- // Paper start - break redstone on trapdoors early
|
||||
- boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
|
||||
- // note: this must run before any state for this block/its neighbours are written to the world
|
||||
- // we allow the redstone event to fire so that plugins can block
|
||||
- if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
|
||||
- // in this case, first check for the redstone on top first
|
||||
- BlockPos abovePos = pos.above();
|
||||
- BlockState above = level.getBlockState(abovePos);
|
||||
- if (above.getBlock() instanceof RedStoneWireBlock) {
|
||||
- level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
|
||||
- Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
|
||||
- // now check that this didn't change our state
|
||||
- if (level.getBlockState(pos) != state) {
|
||||
- // our state was changed, so we cannot propagate this update
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- if (open) {
|
||||
- // Paper end - break redstone on trapdoors early
|
||||
+ if (state.getValue(OPEN) != hasNeighborSignal) {
|
||||
state = state.setValue(OPEN, hasNeighborSignal);
|
||||
this.playSound(null, level, pos, hasNeighborSignal);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 18 Nov 2025 00:35:13 +0800
|
||||
Subject: [PATCH] Leaves: Prevent loss of item drops due to update suppression
|
||||
when breaking blocks
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index 3301e521a79adbc6dd76be05e69cce1c97f8697e..8dc1db0e6bafba19e07a7fa78f3920d572d38466 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -386,7 +386,18 @@ public class ServerPlayerGameMode {
|
||||
this.level.getCurrentWorldData().captureDrops = new java.util.ArrayList<>(); // Folia - region threading
|
||||
// CraftBukkit end
|
||||
BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player);
|
||||
- boolean flag = this.level.removeBlock(pos, false);
|
||||
+ // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks
|
||||
+ boolean flag;
|
||||
+ org.leavesmc.leaves.util.UpdateSuppressionException ex = null;
|
||||
+ try {
|
||||
+ flag = this.level.removeBlock(pos, false);
|
||||
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) {
|
||||
+ ex = e;
|
||||
+ ex.provideBlock(level, pos, block);
|
||||
+ ex.providePlayer(this.player);
|
||||
+ flag = false;
|
||||
+ }
|
||||
+ // Leaves end - Prevent loss of item drops due to update suppression when breaking blocks
|
||||
if (SharedConstants.DEBUG_BLOCK_BREAK) {
|
||||
LOGGER.info("server broke {} {} -> {}", pos, blockState1, this.level.getBlockState(pos));
|
||||
}
|
||||
@@ -418,6 +429,7 @@ public class ServerPlayerGameMode {
|
||||
if (event.isDropItems()) {
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
|
||||
}
|
||||
+ if (ex != null) throw ex; // Leaves - Prevent loss of item drops due to update suppression when breaking blocks
|
||||
|
||||
// Drop event experience
|
||||
if (flag) {
|
||||
+811
@@ -0,0 +1,811 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 18 Nov 2025 23:11:26 +0800
|
||||
Subject: [PATCH] Leaves: Old Block remove behaviour
|
||||
|
||||
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/Containers.java b/net/minecraft/world/Containers.java
|
||||
index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644
|
||||
--- a/net/minecraft/world/Containers.java
|
||||
+++ b/net/minecraft/world/Containers.java
|
||||
@@ -51,4 +51,15 @@ public class Containers {
|
||||
public static void updateNeighboursAfterDestroy(BlockState state, Level level, BlockPos pos) {
|
||||
level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||
}
|
||||
+
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (level.getBlockEntity(pos) instanceof Container container) {
|
||||
+ dropContents(level, pos, container);
|
||||
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||
index dcc1bb4fcee9646212a424c03f77370ffa577fee..ca5cf7526082b9d3a7887dd77313e2c0012efebb 100644
|
||||
--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||
+++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||
@@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
+ if (blockEntity instanceof AbstractFurnaceBlockEntity) {
|
||||
+ if (level instanceof ServerLevel) {
|
||||
+ Containers.dropContents(level, pos, (AbstractFurnaceBlockEntity)blockEntity);
|
||||
+ ((AbstractFurnaceBlockEntity)blockEntity).getRecipesToAwardAndPopExperience((ServerLevel)level, net.minecraft.world.phys.Vec3.atCenterOf(pos));
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ level.updateNeighbourForOutputSignal(pos, this);
|
||||
+ } else {
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
|
||||
index 8139799a24274cfb70a99d301c2688c0360720c6..b224d3756120cd82d1381c55a95ad63c18c123b7 100644
|
||||
--- a/net/minecraft/world/level/block/BarrelBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BarrelBlock.java
|
||||
@@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||
index 7135a6bc87f90fafa94d0783aaf7b42d66449010..afd06de092a75c6c4f7b8848055e314b0c241029 100644
|
||||
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||
@@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ if (this.getSignalForState(state) > 0) {
|
||||
+ this.updateNeighbours(level, pos);
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston && this.getSignalForState(state) > 0) {
|
||||
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
|
||||
index 504f38ce16f6a5d2b748a5c71c69f5be5886ceb5..db0b38db5675cb248e31e7a5988c35496561ad6f 100644
|
||||
--- a/net/minecraft/world/level/block/BaseRailBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
|
||||
@@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving) {
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ if (state.getValue(this.getShapeProperty()).isSlope()) {
|
||||
+ level.updateNeighborsAt(pos.above(), this);
|
||||
+ }
|
||||
+
|
||||
+ if (this.isStraight) {
|
||||
+ level.updateNeighborsAt(pos, this);
|
||||
+ level.updateNeighborsAt(pos.below(), this);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston) {
|
||||
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
index bd6dc109fd9c37666f23ccd17c0eab8aff95e777..e25103c62a41e3fb0a8f7e84496cacc73ed71a74 100644
|
||||
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock {
|
||||
level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
|
||||
index 27ca29f1d3e0e68229edef3b32634ce9b054824a..ea2c5d79fc41f58b263ec34b53df436e0043ef53 100644
|
||||
--- a/net/minecraft/world/level/block/ButtonBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ButtonBlock.java
|
||||
@@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
|
||||
return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff();
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ if (state.getValue(POWERED)) {
|
||||
+ this.updateNeighbours(state, level, pos);
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston && state.getValue(POWERED)) {
|
||||
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
|
||||
index b9e11a361e91cf3d5c929330fc0ba59cfe903198..4985fcfef75abbe2be9cd5e6111de4d60237bafa 100644
|
||||
--- a/net/minecraft/world/level/block/CampfireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CampfireBlock.java
|
||||
@@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
+ if (blockEntity instanceof CampfireBlockEntity) {
|
||||
+ net.minecraft.world.Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems());
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier, boolean pastEdges) {
|
||||
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
|
||||
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
|
||||
index fa2dce759419f62825000718361f47c6f208cdb2..64c0616c294bd7c7b62ae376d50369500b948390 100644
|
||||
--- a/net/minecraft/world/level/block/ChestBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ChestBlock.java
|
||||
@@ -280,6 +280,14 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
|
||||
return this.chestCanConnectTo(blockState) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null;
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||
index cea0f015290137a5284f4a3021c954272b3db543..53d983505b4c92824083ecd123901874d04704c5 100644
|
||||
--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||
@@ -149,6 +149,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl
|
||||
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (level.getBlockEntity(pos) instanceof ChiseledBookShelfBlockEntity chiseledBookShelfBlockEntity && !chiseledBookShelfBlockEntity.isEmpty()) {
|
||||
+ for (int i = 0; i < 6; i++) {
|
||||
+ ItemStack item = chiseledBookShelfBlockEntity.getItem(i);
|
||||
+ if (!item.isEmpty()) {
|
||||
+ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), item);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ chiseledBookShelfBlockEntity.clearContent();
|
||||
+ level.updateNeighbourForOutputSignal(pos, this);
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
index 3faa541c4a4623e915269d6241e1a3a3c6e374ff..18c660893a33ecf70c3d225525505852e4449182 100644
|
||||
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
@@ -128,6 +128,14 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||
index dfb9a10622ba2a0c2759bb563fefd729f1109865..c735e7de1b88de531dd00a2cc2dd4a1394b808e6 100644
|
||||
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
|
||||
builder.add(AXIS, STATE, NATURAL);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ if (level.getBlockEntity(pos) instanceof CreakingHeartBlockEntity creakingHeartBlockEntity) {
|
||||
+ creakingHeartBlockEntity.removeProtector(null);
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||
index dd20e3c57352859ab931692445c83669da94f629..e8c216831b66cd0f4e989797030119388a3378a5 100644
|
||||
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||
@@ -164,6 +164,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
|
||||
return new DecoratedPotBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
|
||||
index b34e051b4a672d44872a74e810f978373e73af05..4525d718016fe125e3cdb1c1798fe9483213ba49 100644
|
||||
--- a/net/minecraft/world/level/block/DiodeBlock.java
|
||||
+++ b/net/minecraft/world/level/block/DiodeBlock.java
|
||||
@@ -176,6 +176,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
|
||||
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ this.updateNeighborsInFront(level, pos, state);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston) {
|
||||
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
|
||||
index 2ef2861041f3aaf85ea64458c43c5d83fdab9bfc..0828d663647f7c3267a4a9392a3b0b8e6e54928c 100644
|
||||
--- a/net/minecraft/world/level/block/DispenserBlock.java
|
||||
+++ b/net/minecraft/world/level/block/DispenserBlock.java
|
||||
@@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock {
|
||||
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
|
||||
index 3c349b4216d934068c26017820884593662f471e..4c5a12784e97e599891d40d5ce784b4f8c1e5b15 100644
|
||||
--- a/net/minecraft/world/level/block/HopperBlock.java
|
||||
+++ b/net/minecraft/world/level/block/HopperBlock.java
|
||||
@@ -133,6 +133,14 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
|
||||
index a4b824dab307705559a76b954a3e47d30dd65889..bc036d8e9d241ea9178808fce39c4e5115d5f753 100644
|
||||
--- a/net/minecraft/world/level/block/JukeboxBlock.java
|
||||
+++ b/net/minecraft/world/level/block/JukeboxBlock.java
|
||||
@@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (level.getBlockEntity(pos) instanceof JukeboxBlockEntity jukeboxBlockEntity) {
|
||||
+ jukeboxBlockEntity.popOutTheItem();
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
|
||||
index 52b9bd310c731c407fc4264559084debec81d3d9..0b991825d48ad64c1c68fd7c6bded7583572dded 100644
|
||||
--- a/net/minecraft/world/level/block/LecternBlock.java
|
||||
+++ b/net/minecraft/world/level/block/LecternBlock.java
|
||||
@@ -198,6 +198,36 @@ public class LecternBlock extends BaseEntityBlock {
|
||||
changePowered(level, pos, state, false);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (state.getValue(HAS_BOOK)) {
|
||||
+ this.popBook(state, level, pos);
|
||||
+ }
|
||||
+
|
||||
+ if (state.getValue(POWERED)) {
|
||||
+ updateBelow(level, pos, state);
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void popBook(BlockState state, Level level, BlockPos pos) {
|
||||
+ if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already // Leaves - the method with validate arg already removed by paper...
|
||||
+ Direction direction = state.getValue(FACING);
|
||||
+ ItemStack itemStack = lecternBlockEntity.getBook().copy();
|
||||
+ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
|
||||
+ float f = 0.25F * direction.getStepX();
|
||||
+ float f1 = 0.25F * direction.getStepZ();
|
||||
+ net.minecraft.world.entity.item.ItemEntity itemEntity = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack);
|
||||
+ itemEntity.setDefaultPickUpDelay();
|
||||
+ level.addFreshEntity(itemEntity);
|
||||
+ lecternBlockEntity.clearContent();
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (state.getValue(POWERED)) {
|
||||
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
|
||||
index 5f03e9fed3d4a8c3b72ca05be0b62ef45ac291f7..359fe5d611bcebe4cb98b9d8cea26b255adb167e 100644
|
||||
--- a/net/minecraft/world/level/block/LeverBlock.java
|
||||
+++ b/net/minecraft/world/level/block/LeverBlock.java
|
||||
@@ -124,6 +124,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ if (state.getValue(POWERED)) {
|
||||
+ this.updateNeighbours(state, level, pos);
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston && state.getValue(POWERED)) {
|
||||
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
|
||||
index dbfe086123c4b3cdc866111e1b6ec37d8d38d394..adad6e538b128729b72b7d44cabbd0cfba7417f9 100644
|
||||
--- a/net/minecraft/world/level/block/LightningRodBlock.java
|
||||
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
|
||||
@@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (state.getValue(POWERED)) {
|
||||
+ this.updateNeighbours(state, level, pos);
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (state.getValue(POWERED)) {
|
||||
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
|
||||
index 3c12d8e23f20b666b0005e597ba2e803c02d5d78..17c371f4c24e8a81705bdd322b1de5de4b8be8b7 100644
|
||||
--- a/net/minecraft/world/level/block/ObserverBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ObserverBlock.java
|
||||
@@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
|
||||
+ this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.FALSE));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
|
||||
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index 48f9e234e4025633cbc41d334d88ada36c2e0d7b..5c154d15e5aa45988436722595c7fca74e166c9a 100644
|
||||
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -368,6 +368,27 @@ public class RedStoneWireBlock extends Block {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ for (Direction direction : Direction.values()) {
|
||||
+ level.updateNeighborsAt(pos.relative(direction), this);
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - optimize redstone - replace call to updatePowerStrength
|
||||
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
|
||||
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
|
||||
+ } else {
|
||||
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
|
||||
+ }
|
||||
+ // Paper end - optimize redstone
|
||||
+ this.updateNeighborsOfNeighboringWires(level, pos);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston) {
|
||||
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
index d1dbfc821f068f14bf975842f66251816ea5c985..fe13504a7d2d685e43183dd7b3219f1605570adb 100644
|
||||
--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
+++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||
@@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving) {
|
||||
+ this.notifyNeighbors(level, pos, state);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston) {
|
||||
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||
index 80e6ba8f026a6565696f18304507b2d0a347650c..593fab3d2a70bcd6832dd777afa4973f22abbaeb 100644
|
||||
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||
@@ -128,6 +128,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ if (getPhase(state) == SculkSensorPhase.ACTIVE) {
|
||||
+ updateNeighbours(level, pos, state);
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
|
||||
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||
index 2815fb48530de3a2f9ef0f472a0fd0a2c32140b6..6b5e5bbbeb11bd8ce100ef3c215dfcf4b387e595 100644
|
||||
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
|
||||
super.stepOn(level, pos, state, entity);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) {
|
||||
+ serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel));
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
if (state.getValue(SHRIEKING)) {
|
||||
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
index 77840814806c7d07b58cd716cf7ec095e894498a..e820cd03e695649a8f83e23ae822524a8f78e23b 100644
|
||||
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
@@ -150,6 +150,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||
// Paper end - re-set loot table if it was cleared
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
+ if (blockEntity instanceof ShulkerBoxBlockEntity) {
|
||||
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||
+ }
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
|
||||
index 9d005c3db8f0c784cdd7217e7b110daa703a9cf3..190d7cd818f768bd44fc1b4e62af2c9b3aacbe4d 100644
|
||||
--- a/net/minecraft/world/level/block/TripWireBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TripWireBlock.java
|
||||
@@ -108,6 +108,16 @@ public class TripWireBlock extends Block {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE));
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
|
||||
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index 42a5e9a7f5d604e4821a116ba13319df052faf97..e90e142cfb15335522a48ad82aa90018ed8ec349 100644
|
||||
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -244,6 +244,25 @@ public class TripWireHookBlock extends Block {
|
||||
level.updateNeighborsAt(pos.relative(opposite), block, orientation);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||
+ boolean attachedValue = state.getValue(ATTACHED);
|
||||
+ boolean poweredValue = state.getValue(POWERED);
|
||||
+ if (attachedValue || poweredValue) {
|
||||
+ calculateState(level, pos, state, true, false, -1, null);
|
||||
+ }
|
||||
+
|
||||
+ if (poweredValue) {
|
||||
+ notifyNeighbors(this, level, pos, state.getValue(FACING));
|
||||
+ }
|
||||
+
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
if (!movedByPiston) {
|
||||
diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||
index 6a9d23d25a79c73d5792011faf0e5a1c4c25bc64..84e0d3cd3c349f0d588a4b4c2d6844480a92b4ca 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||
@@ -306,7 +306,7 @@ public class BlockEntityType<T extends BlockEntity> {
|
||||
}
|
||||
|
||||
public boolean isValid(BlockState state) {
|
||||
- return this.validBlocks.contains(state.getBlock());
|
||||
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour || this.validBlocks.contains(state.getBlock()); // Leaves - behaviour 1.21.1-
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||
index 58b78e6b9a43605940420d8cb0f1163ee3f0a5ff..eebf03ece11052f07702951b9335bc151e160848 100644
|
||||
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||
@@ -65,6 +65,18 @@ public class MovingPistonBlock extends BaseEntityBlock {
|
||||
return createTickerHelper(blockEntityType, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
+ if (blockEntity instanceof PistonMovingBlockEntity) {
|
||||
+ ((PistonMovingBlockEntity)blockEntity).finalTick();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
public void destroy(LevelAccessor level, BlockPos pos, BlockState state) {
|
||||
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||
index b369e80a4fc371a3762e34e7d4d180b86d1d190f..0b412e360b090dc85d1726eb8f51c69b47061276 100644
|
||||
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
|
||||
return super.playerWillDestroy(level, pos, state, player);
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ @Override
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
+ if (!state.is(newState.getBlock())) {
|
||||
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||
+ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||
+ if (this.isFittingBase(state, level.getBlockState(blockPos))) {
|
||||
+ level.destroyBlock(blockPos, true);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
@Override
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4daf68cfd3 100644
|
||||
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -171,6 +171,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
|
||||
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
|
||||
+ if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
|
||||
+ level.removeBlockEntity(pos);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
}
|
||||
|
||||
@@ -866,6 +875,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
+ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston);
|
||||
+ }
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
+
|
||||
public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 5551d80a81c2878136f96b3e695c4888c7105a49..73dd8e67938fbfff745b189c06a93174976ba1bf 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -406,22 +406,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
boolean flag = !blockState.is(block);
|
||||
boolean flag1 = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0;
|
||||
boolean flag2 = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
|
||||
- if (flag && blockState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(blockState)) {
|
||||
- if (!this.level.isClientSide() && flag2) {
|
||||
- BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||
- if (blockEntity != null) {
|
||||
- blockEntity.preRemoveSideEffects(pos, blockState);
|
||||
+ // Leaves start - behaviour 1.21.1-
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) {
|
||||
+ if (flag && blockState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(blockState)) {
|
||||
+ if (!this.level.isClientSide() && flag2) {
|
||||
+ BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||
+ if (blockEntity != null) {
|
||||
+ blockEntity.preRemoveSideEffects(pos, blockState);
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
|
||||
- this.removeBlockEntity(pos);
|
||||
- }
|
||||
+ this.removeBlockEntity(pos);
|
||||
+ }
|
||||
|
||||
- if ((flag || block instanceof BaseRailBlock)
|
||||
- && this.level instanceof ServerLevel serverLevel
|
||||
- && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
|
||||
- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
|
||||
+ if ((flag || block instanceof BaseRailBlock)
|
||||
+ && this.level instanceof ServerLevel serverLevel
|
||||
+ && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
|
||||
+ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ blockState.onRemove(this.level, pos, state, flag1);
|
||||
}
|
||||
+ // Leaves end - behaviour 1.21.1-
|
||||
|
||||
if (!section.getBlockState(i, i1, i2).is(block)) {
|
||||
return null;
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 18 Nov 2025 23:26:27 +0800
|
||||
Subject: [PATCH] Leaves: Do not reset placed block on exception & Do not
|
||||
prevent block entity and entity crash at LevelChunk
|
||||
|
||||
Co-authored by: MC_XiaoHei <xiaohei.xor7@outlook.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/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||
index a5d3caab2072b2c9bf8fdcbdb7c52c2dee16cfaf..4bb36d2965785fadf628a9bfac4fa2aa305aaf65 100644
|
||||
--- a/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/net/minecraft/world/item/BlockItem.java
|
||||
@@ -77,20 +77,22 @@ public class BlockItem extends Item {
|
||||
BlockState blockState = level.getBlockState(clickedPos);
|
||||
if (blockState.is(placementState.getBlock())) {
|
||||
blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState);
|
||||
+ // Leaves start - we do not need this
|
||||
// Paper start - Reset placed block on exception
|
||||
- try {
|
||||
+ // try {
|
||||
this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState);
|
||||
updateBlockEntityComponents(level, clickedPos, itemInHand);
|
||||
- } catch (Exception ex) {
|
||||
- ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
|
||||
- if (player instanceof ServerPlayer serverPlayer) {
|
||||
- org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
|
||||
- serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
|
||||
- return InteractionResult.FAIL;
|
||||
- }
|
||||
- throw ex; // Rethrow exception if not placed by a player
|
||||
- }
|
||||
+ // } catch (Exception ex) {
|
||||
+ // ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
|
||||
+ // if (player instanceof ServerPlayer serverPlayer) {
|
||||
+ // org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
|
||||
+ // serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
|
||||
+ // return InteractionResult.FAIL;
|
||||
+ // }
|
||||
+ // throw ex; // Rethrow exception if not placed by a player
|
||||
+ // }
|
||||
// Paper end - Reset placed block on exception
|
||||
+ // Leaves end - we dot not need this
|
||||
blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand);
|
||||
// CraftBukkit start
|
||||
if (bukkitState != null) {
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 73dd8e67938fbfff745b189c06a93174976ba1bf..8e56c2237f9d49d0b09b62c0933283f77aaae679 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -1001,12 +1001,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
|
||||
profilerFiller.pop();
|
||||
} catch (Throwable var5) {
|
||||
+ // Leaves start - do not prevent here
|
||||
// Paper start - Prevent block entity and entity crashes
|
||||
- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
|
||||
- net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
|
||||
- net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
|
||||
- LevelChunk.this.removeBlockEntity(this.getPos());
|
||||
+ // final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
|
||||
+ // net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
|
||||
+ // net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
|
||||
+ // LevelChunk.this.removeBlockEntity(this.getPos());
|
||||
// Paper end - Prevent block entity and entity crashes
|
||||
+ // Leaves end - do not prevent here
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,302 @@
|
||||
package fun.bm.lophine.protocol;
|
||||
|
||||
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||
import io.papermc.paper.adventure.PaperAdventure;
|
||||
import io.papermc.paper.threadedregions.RegionizedWorldData;
|
||||
import io.papermc.paper.threadedregions.TickRegionScheduler;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTickRateManager;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.NaturalSpawner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
import org.leavesmc.leaves.util.HopperCounter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@LeavesProtocol.Register(namespace = "carpet")
|
||||
public class CarpetLoggerProtocol implements LeavesProtocol {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("CarpetLoggerProtocol");
|
||||
private static final Map<String, Map<String, String>> PLAYER_SUBSCRIPTIONS = new ConcurrentHashMap<>();
|
||||
private static volatile Map<String, String> configuredSubscriptions = null;
|
||||
|
||||
public static void refreshConfiguredDefaults(boolean initial) {
|
||||
Map<String, String> defaults = parseConfiguredDefaults(GeneralCompatConfig.defaultLoggers);
|
||||
configuredSubscriptions = defaults;
|
||||
if (defaults == null || defaults.isEmpty()) {
|
||||
PLAYER_SUBSCRIPTIONS.clear();
|
||||
if (initial) return;
|
||||
for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
||||
clearHud(player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
PLAYER_SUBSCRIPTIONS.replaceAll((playerName, ignored) -> defaults);
|
||||
}
|
||||
|
||||
public static String serializeConfiguredDefaults(List<String> configuredLoggers) {
|
||||
List<String> serialized = new ArrayList<>();
|
||||
if (configuredLoggers != null) {
|
||||
for (String entry : configuredLoggers) {
|
||||
if (entry == null) {
|
||||
continue;
|
||||
}
|
||||
String trimmed = entry.trim();
|
||||
if (!trimmed.isEmpty()) {
|
||||
serialized.add(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
return serialized.isEmpty() ? "none" : String.join(",", serialized);
|
||||
}
|
||||
|
||||
@ProtocolHandler.PlayerJoin
|
||||
public static void onPlayerJoin(ServerPlayer player) {
|
||||
if (configuredSubscriptions != null && !configuredSubscriptions.isEmpty()) {
|
||||
PLAYER_SUBSCRIPTIONS.putIfAbsent(player.getScoreboardName(), configuredSubscriptions);
|
||||
}
|
||||
}
|
||||
|
||||
@ProtocolHandler.PlayerLeave
|
||||
public static void onPlayerLeave(ServerPlayer player) {
|
||||
clearHud(player);
|
||||
}
|
||||
|
||||
@ProtocolHandler.Ticker(tickerId = "hud")
|
||||
public static void onHudTick() {
|
||||
if (PLAYER_SUBSCRIPTIONS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
|
||||
Map<String, String> subscriptions = PLAYER_SUBSCRIPTIONS.get(player.getScoreboardName());
|
||||
if (subscriptions == null || subscriptions.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
player.getBukkitEntity().taskScheduler.schedule((LivingEntity livingEntity) -> {
|
||||
if (livingEntity instanceof ServerPlayer scheduledPlayer) {
|
||||
sendHud(server, scheduledPlayer, subscriptions);
|
||||
}
|
||||
}, null, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int tickerInterval(String tickerID) {
|
||||
return "hud".equals(tickerID) ? 20 : 1;
|
||||
}
|
||||
|
||||
private static void sendHud(MinecraftServer server, ServerPlayer player, Map<String, String> subscriptions) {
|
||||
List<net.minecraft.network.chat.Component> lines = new ArrayList<>();
|
||||
subscriptions.forEach((loggerName, option) -> {
|
||||
switch (loggerName) {
|
||||
case "tps" -> lines.add(buildTpsLine(server));
|
||||
case "mobcaps" -> {
|
||||
net.minecraft.network.chat.Component line = buildMobcapsLine(player, option);
|
||||
if (line != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
case "counter" -> lines.addAll(buildCounterLines(server, option));
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
MutableComponent footer = net.minecraft.network.chat.Component.empty();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (i > 0) {
|
||||
footer.append(net.minecraft.network.chat.Component.literal("\n"));
|
||||
}
|
||||
footer.append(lines.get(i));
|
||||
}
|
||||
player.connection.send(new ClientboundTabListPacket(net.minecraft.network.chat.Component.empty(), footer));
|
||||
}
|
||||
|
||||
private static void clearHud(ServerPlayer player) {
|
||||
player.connection.send(new ClientboundTabListPacket(net.minecraft.network.chat.Component.empty(), net.minecraft.network.chat.Component.empty()));
|
||||
}
|
||||
|
||||
private static net.minecraft.network.chat.Component buildTpsLine(MinecraftServer server) {
|
||||
ServerTickRateManager tickManager = server.tickRateManager();
|
||||
ca.spottedleaf.moonrise.common.time.TickData.TickReportData tickData = TickRegionScheduler.getCurrentRegion().getData().getRegionSchedulingHandle().getTickReport5s(System.nanoTime());
|
||||
final double tps = tickData.tpsData().segmentAll().average();
|
||||
final double mspt = tickData.timePerTickData().segmentAll().average() / 1.0E6;
|
||||
|
||||
ChatFormatting color = heatmapColor(mspt, tickManager.millisecondsPerTick());
|
||||
return net.minecraft.network.chat.Component.empty()
|
||||
.append(net.minecraft.network.chat.Component.literal("TPS: ").withStyle(ChatFormatting.GRAY))
|
||||
.append(net.minecraft.network.chat.Component.literal(String.format(Locale.US, "%.1f", tps)).withStyle(color))
|
||||
.append(net.minecraft.network.chat.Component.literal(" MSPT: ").withStyle(ChatFormatting.GRAY))
|
||||
.append(net.minecraft.network.chat.Component.literal(String.format(Locale.US, "%.1f", mspt)).withStyle(color));
|
||||
}
|
||||
|
||||
private static net.minecraft.network.chat.Component buildMobcapsLine(ServerPlayer player, String option) {
|
||||
final ServerLevel level = resolveMobcapsLevel(player, option);
|
||||
if (level == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final RegionizedWorldData data = level.getCurrentWorldData();
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final NaturalSpawner.SpawnState spawnState = data.lastSpawnState;
|
||||
if (spawnState == null) {
|
||||
return net.minecraft.network.chat.Component.literal("Mobcaps: unavailable").withStyle(ChatFormatting.DARK_GRAY);
|
||||
}
|
||||
|
||||
int chunks = spawnState.getSpawnableChunkCount();
|
||||
var counts = spawnState.getMobCategoryCounts();
|
||||
MutableComponent line = net.minecraft.network.chat.Component.literal("Mobcaps").withStyle(ChatFormatting.GRAY);
|
||||
for (MobCategory category : MobCategory.values()) {
|
||||
if (category == MobCategory.MISC) {
|
||||
continue;
|
||||
}
|
||||
int current = counts.getOrDefault(category, 0);
|
||||
int limit = NaturalSpawner.globalLimitForCategory(level, category, chunks);
|
||||
line.append(net.minecraft.network.chat.Component.literal(" " + shortName(category) + " ").withStyle(ChatFormatting.DARK_GRAY));
|
||||
line.append(net.minecraft.network.chat.Component.literal(current + "/" + limit).withStyle(categoryColor(current, limit)));
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
private static List<net.minecraft.network.chat.Component> buildCounterLines(MinecraftServer server, String option) {
|
||||
List<net.minecraft.network.chat.Component> lines = new ArrayList<>();
|
||||
String colors = option == null || option.isBlank() ? "white" : option;
|
||||
for (String rawColor : colors.split(",")) {
|
||||
String colorName = rawColor.trim();
|
||||
if (colorName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
DyeColor color = DyeColor.byName(colorName, null);
|
||||
if (color == null) {
|
||||
continue;
|
||||
}
|
||||
HopperCounter counter = HopperCounter.getCounter(color);
|
||||
if (counter == null) {
|
||||
continue;
|
||||
}
|
||||
for (Component component : counter.format(server, false)) {
|
||||
lines.add(PaperAdventure.asVanilla(component));
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static ServerLevel resolveMobcapsLevel(ServerPlayer player, String option) {
|
||||
if (option == null || option.isBlank() || option.equalsIgnoreCase("dynamic")) {
|
||||
return player.level();
|
||||
}
|
||||
return switch (option.toLowerCase(Locale.ROOT)) {
|
||||
case "overworld" -> player.level().dimension() == Level.OVERWORLD ? player.level() : null;
|
||||
case "nether" -> player.level().dimension() == Level.NETHER ? player.level() : null;
|
||||
case "end" -> player.level().dimension() == Level.END ? player.level() : null;
|
||||
default -> player.level();
|
||||
};
|
||||
}
|
||||
|
||||
private static ChatFormatting heatmapColor(double actual, double reference) {
|
||||
if (actual > reference) {
|
||||
return ChatFormatting.LIGHT_PURPLE;
|
||||
}
|
||||
if (actual > 0.8D * reference) {
|
||||
return ChatFormatting.RED;
|
||||
}
|
||||
if (actual > 0.5D * reference) {
|
||||
return ChatFormatting.YELLOW;
|
||||
}
|
||||
if (actual >= 0.0D) {
|
||||
return ChatFormatting.DARK_GREEN;
|
||||
}
|
||||
return ChatFormatting.GRAY;
|
||||
}
|
||||
|
||||
private static ChatFormatting categoryColor(int current, int limit) {
|
||||
if (limit <= 0) {
|
||||
return ChatFormatting.DARK_GRAY;
|
||||
}
|
||||
double ratio = current / (double) limit;
|
||||
if (ratio >= 1.0D) {
|
||||
return ChatFormatting.RED;
|
||||
}
|
||||
if (ratio >= 0.8D) {
|
||||
return ChatFormatting.YELLOW;
|
||||
}
|
||||
return ChatFormatting.GREEN;
|
||||
}
|
||||
|
||||
private static String shortName(MobCategory category) {
|
||||
return switch (category) {
|
||||
case MONSTER -> "M";
|
||||
case CREATURE -> "C";
|
||||
case AMBIENT -> "A";
|
||||
case AXOLOTLS -> "Ax";
|
||||
case UNDERGROUND_WATER_CREATURE -> "UWC";
|
||||
case WATER_CREATURE -> "WC";
|
||||
case WATER_AMBIENT -> "WA";
|
||||
case MISC -> "X";
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, String> parseConfiguredDefaults(List<String> configuredLoggers) {
|
||||
LinkedHashMap<String, String> subscriptions = new LinkedHashMap<>();
|
||||
if (configuredLoggers == null) {
|
||||
return null;
|
||||
}
|
||||
for (String entry : configuredLoggers) {
|
||||
if (entry == null) {
|
||||
continue;
|
||||
}
|
||||
for (String chunk : entry.split(",")) {
|
||||
String token = chunk.trim();
|
||||
if (token.isEmpty() || token.equalsIgnoreCase("none")) {
|
||||
continue;
|
||||
}
|
||||
String[] parts = token.split("\\s+", 2);
|
||||
String loggerName = parts[0].toLowerCase(Locale.ROOT);
|
||||
if (!isSupported(loggerName)) {
|
||||
LOGGER.debug("Ignoring unsupported Carpet default logger '{}'", loggerName);
|
||||
continue;
|
||||
}
|
||||
String option = parts.length == 1 ? defaultOption(loggerName) : parts[1].trim();
|
||||
if (option.isEmpty()) {
|
||||
option = defaultOption(loggerName);
|
||||
}
|
||||
subscriptions.put(loggerName, option);
|
||||
}
|
||||
}
|
||||
return subscriptions.isEmpty() ? null : Map.copyOf(subscriptions);
|
||||
}
|
||||
|
||||
private static boolean isSupported(String loggerName) {
|
||||
return Arrays.asList("tps", "mobcaps", "counter").contains(loggerName);
|
||||
}
|
||||
|
||||
private static @NotNull String defaultOption(String loggerName) {
|
||||
return switch (loggerName) {
|
||||
case "mobcaps" -> "dynamic";
|
||||
case "counter" -> "white";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package fun.bm.lophine.protocol.tiscm;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||
import io.papermc.paper.ServerBuildInfo;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@LeavesProtocol.Register(namespace = TISCMProtocol.PROTOCOL_ID)
|
||||
public class TISCMProtocol implements LeavesProtocol {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static final String PROTOCOL_ID = "tiscm";
|
||||
private static final String PLATFORM_NAME = "Lophine";
|
||||
private static final String PLATFORM_VERSION = ServerBuildInfo.buildInfo().asString(ServerBuildInfo.StringRepresentation.VERSION_SIMPLE);
|
||||
private static final Map<String, EnumSet<S2CPacket>> CLIENT_SUPPORTED_PACKETS = new ConcurrentHashMap<>();
|
||||
|
||||
@Contract("_ -> new")
|
||||
public static Identifier id(String path) {
|
||||
return Identifier.fromNamespaceAndPath(PROTOCOL_ID, path);
|
||||
}
|
||||
|
||||
public static void broadcastMsptSample(long tickCounter, long nanosecond) {
|
||||
if (!GeneralCompatConfig.tiscmNetworkProtocol || !GeneralCompatConfig.syncServerMsptMetricsData) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
nbt.putInt("version", 2);
|
||||
nbt.putLong("millisecond", nanosecond / 1_000_000L);
|
||||
nbt.putLong("nanosecond", nanosecond);
|
||||
nbt.putString("type", "tick_server_method");
|
||||
|
||||
TISCMPayload payload = new TISCMPayload(S2CPacket.MSPT_METRICS_SAMPLE.id, nbt);
|
||||
for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
||||
if (supports(player, S2CPacket.MSPT_METRICS_SAMPLE)) {
|
||||
ProtocolUtils.sendPayloadPacket(player, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ProtocolHandler.PayloadReceiver(payload = TISCMPayload.class)
|
||||
public static void handlePayload(ServerPlayer player, TISCMPayload payload) {
|
||||
if (!GeneralCompatConfig.tiscmNetworkProtocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<C2SPacket> packetType = C2SPacket.fromId(payload.packetId());
|
||||
if (packetType.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (packetType.get()) {
|
||||
case HI -> handleHi(player, payload.nbt());
|
||||
case SUPPORTED_S2C_PACKETS -> handleSupportedS2CPackets(player, payload.nbt());
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ProtocolHandler.PlayerLeave
|
||||
public static void onPlayerLeave(ServerPlayer player) {
|
||||
CLIENT_SUPPORTED_PACKETS.remove(player.getStringUUID());
|
||||
}
|
||||
|
||||
private static void handleHi(ServerPlayer player, CompoundTag payload) {
|
||||
String platformName = payload.getString("platform_name").orElse("Unknown");
|
||||
String platformVersion = payload.getString("platform_version").orElse("Unknown");
|
||||
LOGGER.info("Player {} connected with TISCM protocol support ({} @ {})", player.getScoreboardName(), platformName, platformVersion);
|
||||
|
||||
send(player, S2CPacket.HELLO, nbt -> {
|
||||
nbt.putString("platform_name", PLATFORM_NAME);
|
||||
nbt.putString("platform_version", PLATFORM_VERSION);
|
||||
});
|
||||
send(player, S2CPacket.SUPPORTED_C2S_PACKETS, nbt -> nbt.put("supported_c2s_packets", stringList(List.of(
|
||||
C2SPacket.HI.id,
|
||||
C2SPacket.SUPPORTED_S2C_PACKETS.id
|
||||
))));
|
||||
}
|
||||
|
||||
private static void handleSupportedS2CPackets(ServerPlayer player, CompoundTag payload) {
|
||||
EnumSet<S2CPacket> packets = EnumSet.noneOf(S2CPacket.class);
|
||||
ListTag listTag = payload.getListOrEmpty("supported_s2c_packets");
|
||||
for (int i = 0; i < listTag.size(); i++) {
|
||||
S2CPacket.fromId(listTag.getString(i).orElse("")).ifPresent(packets::add);
|
||||
}
|
||||
CLIENT_SUPPORTED_PACKETS.put(player.getStringUUID(), packets);
|
||||
}
|
||||
|
||||
private static void send(ServerPlayer player, S2CPacket packet, PayloadBuilder builder) {
|
||||
if (!supports(player, packet)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
builder.accept(nbt);
|
||||
ProtocolUtils.sendPayloadPacket(player, new TISCMPayload(packet.id, nbt));
|
||||
}
|
||||
|
||||
private static boolean supports(ServerPlayer player, S2CPacket packet) {
|
||||
if (packet.handshake) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EnumSet<S2CPacket> packets = CLIENT_SUPPORTED_PACKETS.get(player.getStringUUID());
|
||||
return packets != null && packets.contains(packet);
|
||||
}
|
||||
|
||||
private static ListTag stringList(List<String> values) {
|
||||
ListTag list = new ListTag();
|
||||
for (String value : values) {
|
||||
list.add(StringTag.valueOf(value));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return GeneralCompatConfig.tiscmNetworkProtocol;
|
||||
}
|
||||
|
||||
private interface PayloadBuilder {
|
||||
void accept(CompoundTag nbt);
|
||||
}
|
||||
|
||||
public enum C2SPacket {
|
||||
HI("hi", true),
|
||||
SUPPORTED_S2C_PACKETS("supported_s2c_packets", true),
|
||||
SPEED_TEST_UPLOAD_PAYLOAD("speed_test_upload_payload", false),
|
||||
SPEED_TEST_PING("speed_test_ping", false);
|
||||
|
||||
private static final Map<String, C2SPacket> BY_ID = Arrays.stream(values()).collect(Collectors.toMap(packet -> packet.id, packet -> packet));
|
||||
|
||||
private final String id;
|
||||
private final boolean handshake;
|
||||
|
||||
C2SPacket(String id, boolean handshake) {
|
||||
this.id = id;
|
||||
this.handshake = handshake;
|
||||
}
|
||||
|
||||
public static Optional<C2SPacket> fromId(String id) {
|
||||
return Optional.ofNullable(BY_ID.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
public enum S2CPacket {
|
||||
HELLO("hello", true),
|
||||
SUPPORTED_C2S_PACKETS("supported_c2s_packets", true),
|
||||
MSPT_METRICS_SAMPLE("mspt_metrics_sample", false),
|
||||
SPEED_TEST_DOWNLOAD_PAYLOAD("speed_test_download_payload", false),
|
||||
SPEED_TEST_UPLOAD_REQUEST("speed_test_upload_request", false),
|
||||
SPEED_TEST_PING("speed_test_ping", false),
|
||||
SPEED_TEST_ABORT("speed_test_abort", false);
|
||||
|
||||
private static final Map<String, S2CPacket> BY_ID = Arrays.stream(values()).collect(Collectors.toMap(packet -> packet.id, packet -> packet));
|
||||
|
||||
private final String id;
|
||||
private final boolean handshake;
|
||||
|
||||
S2CPacket(String id, boolean handshake) {
|
||||
this.id = id;
|
||||
this.handshake = handshake;
|
||||
}
|
||||
|
||||
public static Optional<S2CPacket> fromId(String id) {
|
||||
return Optional.ofNullable(BY_ID.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
public record TISCMPayload(String packetId, CompoundTag nbt) implements LeavesCustomPayload {
|
||||
@ID
|
||||
private static final Identifier NETWORK_ID = TISCMProtocol.id("network/v1");
|
||||
|
||||
@Codec
|
||||
private static final StreamCodec<RegistryFriendlyByteBuf, TISCMPayload> CODEC = StreamCodec.composite(
|
||||
ByteBufCodecs.STRING_UTF8,
|
||||
TISCMPayload::packetId,
|
||||
ByteBufCodecs.COMPOUND_TAG,
|
||||
TISCMPayload::nbt,
|
||||
TISCMPayload::new
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -78,7 +78,7 @@ dependencies {
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
</dependency>
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -78,7 +78,7 @@ dependencies {
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
<scope>provided</scope>
|
||||
|
||||
+7
-4
@@ -3,14 +3,17 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||
|
||||
plugins {
|
||||
java // TODO java launcher tasks
|
||||
id("moe.luminolmc.hyacinthusweight.patcher") version "+" // Automatically pulls the latest
|
||||
id("moe.luminolmc.hyacinthusweight.patcher")
|
||||
}
|
||||
|
||||
paperweight {
|
||||
filterPatches = false
|
||||
upstreams.register("luminol") {
|
||||
repo = github("LuminolMC", "Luminol")
|
||||
ref = providers.gradleProperty("luminolRef")
|
||||
|
||||
println("Upstream commit ref: " + ref.get())
|
||||
|
||||
patchFile {
|
||||
path = "luminol-server/build.gradle.kts"
|
||||
outputFile = file("lophine-server/build.gradle.kts")
|
||||
@@ -49,7 +52,7 @@ subprojects {
|
||||
|
||||
extensions.configure<JavaPluginExtension> {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
languageVersion = JavaLanguageVersion.of(25)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +72,7 @@ subprojects {
|
||||
}
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release = 21
|
||||
options.release = 25
|
||||
options.isFork = true
|
||||
}
|
||||
tasks.withType<Javadoc>().configureEach {
|
||||
@@ -106,4 +109,4 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
### Carpet 原版
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `language` | 已映射 | 转发到 `lophine.function.language.lang` |
|
||||
| `commandTick` | 已映射 | 转发到现有的 tick 指令补丁 |
|
||||
| `creativeNoClip` | 已映射 | 转发到 Lophine 的创造飞行穿墙实现 |
|
||||
| `ctrlQCraftingFix` | 结构等价 | 当前的合成与切石机菜单已经自带修复后的 Ctrl+Q 结果槽丢弃行为 |
|
||||
| `placementRotationFix` | 已移植 | 放置朝向判断可使用玩家身体朝向而不是头部旋转 |
|
||||
| `tntDoNotUpdate` | 已移植 | 新放置的 TNT 不会再因放置时更新而自动点燃 |
|
||||
| `explosionNoBlockDamage` | 已移植 | 爆炸仍会伤害实体,但不会破坏方块 |
|
||||
| `interactionUpdates` | 已移植 | 玩家交互和破坏方块时可以在不触发邻居更新与形状更新的情况下运行 |
|
||||
| `xpNoCooldown` | 已移植 | 经验球可以在同一 tick 内被连续吸收,不再有拾取冷却 |
|
||||
| `viewDistance` | 已移植 | 专用服务器启动视距会被兼容配置覆盖 |
|
||||
| `fastRedstoneDust` | 已移植 | 规则启用时,红石粉更新会统一走 Alternate Current 快速更新后端 |
|
||||
| `lagFreeSpawning` | 已移植 | 自然生成会使用轻量碰撞检查与预构造实体路径 |
|
||||
| `defaultLoggers` | 已移植 | 按 Carpet 默认订阅语义为玩家启用 HUD logger,当前支持 `tps`、`mobcaps`、`counter` |
|
||||
| `commandPlayer` | 已映射 | 当前由同一套 `/bot` 假人能力承接 |
|
||||
| `hopperCounters` | 已映射 | 转发到 Lophine 的羊毛漏斗计数器 |
|
||||
|
||||
### Carpet TIS Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `yeetUpdateSuppressionCrash` | 已映射 | 转发到同一套 Lophine 崩溃修复逻辑 |
|
||||
| `dustTrapdoorReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.redstone-ignore-upwards-update` |
|
||||
| `shulkerBoxCCEReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.cce-update-suppression` |
|
||||
| `instantBlockUpdaterReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.instant-block-updater` |
|
||||
| `optimizedDragonRespawn` | 已映射 | 转发到 Luminol 的末影龙重生优化 |
|
||||
| `antiSpamDisabled` | 已移植 | 在 `ServerGamePacketListenerImpl` 中关闭聊天和创造丢物防刷屏限制 |
|
||||
| `blockPlacementIgnoreEntity` | 已移植 | 创造模式放置方块时忽略实体碰撞检查 |
|
||||
| `creativeOpenContainerForcibly` | 已移植 | 创造玩家可以强制打开被阻挡的箱子、末影箱和潜影盒 |
|
||||
| `observerNoDetection` | 已移植 | 观察者的检测触发会在发出脉冲前被取消 |
|
||||
| `creativeNoItemCooldown` | 已移植 | 创造玩家不会应用物品冷却 |
|
||||
| `totallyNoBlockUpdate` | 已移植 | 邻居更新和形状更新会在 `NeighborUpdater` 中被统一短路 |
|
||||
| `tiscmNetworkProtocol` | 已移植 | 原生 `tiscm:network/v1` 握手与数据包协商已经通过专用 Leaves 协议接入 |
|
||||
| `optimizedTNTHighPriority` | 结构等价 | 当前 `ServerExplosion` 路径已经运行在优化过的服务端爆炸实现上 |
|
||||
| `tntIgnoreRedstoneSignal` | 已移植 | TNT 在自动点燃判断时忽略红石信号 |
|
||||
| `tntDupingFix` | 已移植 | 活塞复制 TNT 的路径现在由 `PistonBaseBlock` 中的兼容规则直接控制 |
|
||||
| `clientSettingsLostOnRespawnFix` | 已移植 | 玩家上一次的客户端设置会在 `ServerPlayer.restoreFrom` 中恢复 |
|
||||
| `entityInstantDeathRemoval` | 已移植 | 已死亡生物不会再保留原版的 20gt 延迟,而是立即移除 |
|
||||
| `farmlandTrampledDisabled` | 已移植 | 耕地不会再因实体踩踏而变回泥土 |
|
||||
| `yeetOutOfOrderChatKick` | 已移植 | 乱序的签名聊天不会再破坏安全聊天链 |
|
||||
| `tickCommandPermission` | 已移植 | `/tick` 的权限等级可通过兼容配置调整 |
|
||||
| `tickFreezeCommandToggleable` | 已移植 | 已冻结时再次执行 `/tick freeze` 会切换回运行状态 |
|
||||
| `syncServerMsptMetricsData` | 已移植 | 实时 MSPT 样本会通过原生 TISCM 协议通道广播 |
|
||||
| `microTiming` | 结构等价 | 当前 Folia 的区块级性能分析与计时钩子已经提供对应的服务端观测能力 |
|
||||
| `optimizedFastEntityMovement` | 结构等价 | Moonrise/Paper 的快速实体移动碰撞优化已经是基础运行时的一部分 |
|
||||
| `optimizedHardHitBoxEntityCollision` | 结构等价 | Moonrise/Paper 的硬碰撞箱实体碰撞优化已经是基础运行时的一部分 |
|
||||
| `tntFuseDuration` | 已移植 | 可配置的 TNT 引信时长已接入 NMS TNT 逻辑 |
|
||||
| `fakePlayerTicksLikeRealPlayer` | 已映射 | 转发到 Leaves 的假人网络阶段 tick 行为 |
|
||||
| `hopperCountersUnlimitedSpeed` | 已映射 | 转发到不限速计数器模式 |
|
||||
|
||||
### Carpet Org Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `hopperNoItemCost` | 已移植 | 漏斗上方放置羊毛时,可在传输后恢复被推出的物品堆,实现零消耗供给线 |
|
||||
| `simpleInGameCalculator` | 已移植 | 以 `=` 开头的聊天内容会作为简单计算表达式私聊回复 |
|
||||
|
||||
### Carpet AMS Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `amsUpdateSuppressionCrashFix` | 已映射 | 转发到 Lophine 现有的更新抑制崩溃修复 |
|
||||
| `creativeOneHitKill` | 已移植 | 创造玩家可通过 `Player.attack` 瞬间击杀附近符合条件的目标 |
|
||||
| `bambooModelNoOffset` | 已移植 | 竹子和竹笋始终返回零模型偏移 |
|
||||
| `carpetAlwaysSetDefault` | 结构等价 | 兼容配置默认值已经会在 `ConfigsInstance.preLoadConfig` 中被写入 |
|
||||
| `powerfulExpMending` | 已移植 | 经验拾取会修复玩家整个背包内所有受损的经验修补物品 |
|
||||
| `sensibleEnderman` | 已移植 | 末影人仅会在规则开启时拾取南瓜和西瓜 |
|
||||
| `shulkerGolem` | 已移植 | 潜影盒上方放置雕刻南瓜时可以召唤潜影贝 |
|
||||
| `preventEndSpikeRespawn` | 已移植 | 末影龙重生时会跳过黑曜石柱重建和柱顶水晶重建 |
|
||||
| `betterCraftableBoneBlock` | 已移植 | 向配方管理器注入 AMS 的替代骨块配方 |
|
||||
| `betterCraftableDispenser` | 已移植 | 向配方管理器注入 AMS 的替代发射器配方 |
|
||||
| `fakePlayerDefaultSurvivalMode` | 已移植 | 新创建的假人可以被强制设为生存模式,而不是沿用服务器默认游戏模式 |
|
||||
| `fakePlayerInteractLikeClient` | 已移植 | 假人与盔甲架交互时会先按真实客户端方式回退,再进入普通实体交互 |
|
||||
| `fakePlayerAutoReplenishmentFormShulkerBox` | 已移植 | 假人自动补货现在可以从背包里的潜影盒中抽取匹配物品 |
|
||||
|
||||
### Lophine 扩展承接
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- |----------------------------------|
|
||||
| `commandBot` | 已映射 | 启用 Lophine `/bot` |
|
||||
| `fakePlayerResident` | 已映射 | 转发到 Lophine 的假人常驻模式 |
|
||||
| `openFakePlayerInventory` | 已映射 | 转发到 Lophine 的假人背包打开功能 |
|
||||
| `fakePlayerAutoReplaceTool` | 已映射 | 为现有自动换工具逻辑增加了新开关 |
|
||||
| `fakePlayerAutoReplenishment` | 已映射 | 为现有自动补货逻辑增加了新开关 |
|
||||
| `fakePlayerReloadAction` | 已映射 | 为假人动作持久化增加了新开关 |
|
||||
| `fakePlayerAutoFish` | 已移植 | 手持鱼竿的假人会自动抛竿和收杆,除非显式执行 `fish` 动作 |
|
||||
+7
-4
@@ -1,10 +1,13 @@
|
||||
group=fun.bm.lophine
|
||||
version=1.21.8-R0.1-SNAPSHOT
|
||||
mcVersion=1.21.8
|
||||
release=2
|
||||
mcVersion=26.1.2
|
||||
apiVersion=26.1.2
|
||||
channel=BETA
|
||||
clipVersion=3.0.16
|
||||
weightVersion=2.0.12
|
||||
# 0 for skip release, 1 for pre-release, 2 for release
|
||||
release=1
|
||||
|
||||
luminolRef=332099a920bc3e854ba1d37fc5651c0f922e32e8
|
||||
luminolRef=848d8ce4f0de05e43b6879150d9a392324ca7867
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/luminol-api/build.gradle.kts
|
||||
+++ b/luminol-api/build.gradle.kts
|
||||
@@ -103,20 +_,24 @@
|
||||
@@ -104,20 +_,24 @@
|
||||
srcDir(generatedDir)
|
||||
srcDir(file("../paper-api/src/main/java"))
|
||||
srcDir(file("../folia-api/src/main/java"))
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 11 May 2026 10:47:42 +0800
|
||||
Subject: [PATCH] Add cancel task by task id in FoliaGlobalRegionScheduler
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
index 57455aca80ecc458b96b44c086cea94ddcecae47..763d27d303b9a588526445c453e07f5886534e82 100644
|
||||
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
@@ -55,4 +55,10 @@ public interface GlobalRegionScheduler {
|
||||
* @param plugin Specified plugin.
|
||||
*/
|
||||
void cancelTasks(@NotNull Plugin plugin);
|
||||
+
|
||||
+ /**
|
||||
+ * Attempts to cancel the specified task.
|
||||
+ * @param taskId The task id.
|
||||
+ */
|
||||
+ void cancelTask(final int taskId);
|
||||
}
|
||||
+10
-7
@@ -1,17 +1,20 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sat, 30 Aug 2025 16:51:26 +0800
|
||||
Subject: [PATCH] Add fakeplayer api
|
||||
Subject: [PATCH] Leaves: Add fakeplayer api
|
||||
|
||||
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/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113c1296d26 100644
|
||||
index 8e96326c55510642df01ef15e1a3edb1e81176cb..592a3c59bf5edbc65c7c0472e2382593b7b22086 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -3052,4 +3052,15 @@ public final class Bukkit {
|
||||
public static void restart() {
|
||||
server.restart();
|
||||
@@ -3048,4 +3048,15 @@ public final class Bukkit {
|
||||
return server.getFeatureManager();
|
||||
}
|
||||
// Leaves end - Feature API
|
||||
+
|
||||
+ // Leaves start - Bot API
|
||||
+ /**
|
||||
@@ -25,10 +28,10 @@ index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113
|
||||
+ // Leaves end - Bot API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index a0540d7de5c2536aed5231f9e67b73345817921d..c7ae463fb166750bbd0638a2ccf81753b293a381 100644
|
||||
index 473b0e02c003d5317ef798c320e5c845124f4e12..978e015e91408503b4ec84ec5b3c5193255ba7db 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2753,4 +2753,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
@@ -2813,4 +2813,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
double @Nullable [] getRegionTPS(@NotNull World world, int chunkX, int chunkZ);
|
||||
// Folia end - region TPS API
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 15:50:28 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
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/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 592a3c59bf5edbc65c7c0472e2382593b7b22086..838ad878528267b57b69d2938aee0eb6326948eb 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -3059,4 +3059,10 @@ public final class Bukkit {
|
||||
return server.getBotManager();
|
||||
}
|
||||
// Leaves end - Bot API
|
||||
+
|
||||
+ // Leaves start - Photographer API
|
||||
+ public static @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager() {
|
||||
+ return server.getPhotographerManager();
|
||||
+ }
|
||||
+ // Leaves end - Photographer API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 978e015e91408503b4ec84ec5b3c5193255ba7db..d054926f6082bba7d0b59e610e5d725ff5f9ffa4 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2822,4 +2822,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
@NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager();
|
||||
// Leaves end - Bot API
|
||||
+
|
||||
+ // Leaves start - Photographer API
|
||||
+ @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager();
|
||||
+ // Leaves end - Photographer API
|
||||
}
|
||||
@@ -39,9 +39,9 @@ public interface Bot extends Player {
|
||||
/**
|
||||
* Gets the fakeplayer name without prefix and suffix
|
||||
*
|
||||
* @return fakeplayer real name
|
||||
* @return fakeplayer raw name
|
||||
*/
|
||||
@NotNull String getRealName();
|
||||
@NotNull String getRawName();
|
||||
|
||||
/**
|
||||
* Gets the creator's UUID of the fakeplayer
|
||||
@@ -91,4 +91,13 @@ public interface Bot extends Player {
|
||||
* @return success
|
||||
*/
|
||||
boolean remove(boolean save);
|
||||
|
||||
/**
|
||||
* Remove the fakeplayer
|
||||
*
|
||||
* @param save should save
|
||||
* @param resume should resume at next server start
|
||||
* @return success
|
||||
*/
|
||||
boolean remove(boolean save, boolean resume);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import java.util.function.Consumer;
|
||||
|
||||
public interface BotCreator {
|
||||
|
||||
static BotCreator of(String realName, Location location) {
|
||||
return Bukkit.getBotManager().botCreator(realName, location);
|
||||
static BotCreator of(String rawName, Location location) {
|
||||
return Bukkit.getBotManager().botCreator(rawName, location);
|
||||
}
|
||||
|
||||
BotCreator name(String name);
|
||||
|
||||
@@ -61,5 +61,5 @@ public interface BotManager {
|
||||
*/
|
||||
<T extends BotAction<T>> T newAction(@NotNull Class<T> type);
|
||||
|
||||
BotCreator botCreator(@NotNull String realName, @NotNull Location location);
|
||||
BotCreator botCreator(@NotNull String rawName, @NotNull Location location);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.entity.photographer;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface Photographer extends Player {
|
||||
|
||||
@NotNull String getId();
|
||||
|
||||
void setRecordFile(@NotNull File file);
|
||||
|
||||
void stopRecording();
|
||||
|
||||
void stopRecording(boolean async);
|
||||
|
||||
void stopRecording(boolean async, boolean save);
|
||||
|
||||
void pauseRecording();
|
||||
|
||||
void resumeRecording();
|
||||
|
||||
void setFollowPlayer(@Nullable Player player);
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.entity.photographer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.replay.BukkitRecorderOption;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface PhotographerManager {
|
||||
@Nullable Photographer getPhotographer(@NotNull UUID uuid);
|
||||
|
||||
@Nullable Photographer getPhotographer(@NotNull String id);
|
||||
|
||||
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location);
|
||||
|
||||
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption);
|
||||
|
||||
void removePhotographer(@NotNull String id);
|
||||
|
||||
void removePhotographer(@NotNull UUID uuid);
|
||||
|
||||
void removeAllPhotographers();
|
||||
|
||||
Collection<Photographer> getPhotographers();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.replay;
|
||||
|
||||
public class BukkitRecorderOption {
|
||||
|
||||
// public int recordDistance = -1;
|
||||
public String serverName = "Lophine"; // Lophine - rebrand to Lophine to avoid confusion
|
||||
public BukkitRecordWeather forceWeather = BukkitRecordWeather.NULL;
|
||||
public int forceDayTime = -1;
|
||||
public boolean ignoreChat = false;
|
||||
// public boolean ignoreItem = false;
|
||||
|
||||
public enum BukkitRecordWeather {
|
||||
CLEAR,
|
||||
RAIN,
|
||||
THUNDER,
|
||||
NULL
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/luminol-server/build.gradle.kts
|
||||
+++ b/luminol-server/build.gradle.kts
|
||||
@@ -52,7 +_,23 @@
|
||||
@@ -50,7 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
+ activeFork = lophine
|
||||
|
||||
|
||||
spigot {
|
||||
@@ -142,12 +_,16 @@
|
||||
|
||||
@@ -125,12 +_,16 @@
|
||||
resources { srcDir("../paper-server/src/main/resources") }
|
||||
java { srcDir("../folia-server/src/main/java") }
|
||||
resources { srcDir("../folia-server/src/main/resources") }
|
||||
@@ -42,35 +42,35 @@
|
||||
}
|
||||
}
|
||||
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
||||
@@ -174,7 +_,7 @@
|
||||
@@ -158,7 +_,7 @@
|
||||
}
|
||||
|
||||
dependencies {
|
||||
- implementation(project(":luminol-api")) // Luminol
|
||||
+ implementation(project(":lophine-api")) // Lophine
|
||||
- implementation(project(":luminol-api"))
|
||||
+ implementation(project(":lophine-api"))
|
||||
// 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")
|
||||
@@ -275,14 +_,14 @@
|
||||
implementation("net.objecthunter:exp4j:0.4.8")
|
||||
implementation("com.electronwill.night-config:toml:3.8.3") // Night config
|
||||
@@ -234,14 +_,14 @@
|
||||
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
|
||||
attributes(
|
||||
"Main-Class" to "org.bukkit.craftbukkit.Main",
|
||||
- "Implementation-Title" to "Luminol",
|
||||
+ "Implementation-Title" to "Lophine",
|
||||
- "Implementation-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Implementation-Title" to "Lophine", // Luminol - Rebrand
|
||||
"Implementation-Version" to implementationVersion,
|
||||
"Implementation-Vendor" to date,
|
||||
- "Specification-Title" to "Luminol",
|
||||
+ "Specification-Title" to "Lophine",
|
||||
- "Specification-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Specification-Title" to "Lophine", // Luminol - Rebrand
|
||||
"Specification-Version" to project.version,
|
||||
"Specification-Vendor" to "LuminolMC org",
|
||||
- "Brand-Id" to "luminolmc:luminol",
|
||||
- "Brand-Name" to "Luminol",
|
||||
+ "Brand-Id" to "luminolmc:lophine",
|
||||
+ "Brand-Name" to "Lophine",
|
||||
"Specification-Vendor" to "LuminoLMC", // Luminol - Rebrand
|
||||
- "Brand-Id" to "luminolmc:luminol", // Luminol - Rebrand
|
||||
- "Brand-Name" to "Luminol", // Luminol - Rebrand
|
||||
+ "Brand-Id" to "luminolmc:lophine", // Luminol - Rebrand
|
||||
+ "Brand-Name" to "Lophine", // Luminol - Rebrand
|
||||
"Build-Number" to (build ?: ""),
|
||||
"Build-Time" to buildTime.toString(),
|
||||
"Git-Branch" to gitBranch,
|
||||
@@ -446,7 +_,7 @@
|
||||
@@ -393,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 d8066afd5f3f2ea9a5dff87d853562e22268785c..f8b2364fa162a41304a99a4993354e33528ab801 100644
|
||||
index 490316c7d5cbb77e988039cfa7a7cc0aa3849730..f5fb4e210c07f32e52eb8c1ba166d1571a6778c7 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -21,6 +21,7 @@ public class ConfigManager {
|
||||
@@ -24,6 +24,7 @@ public class ConfigManager {
|
||||
|
||||
public static void initConfigs() {
|
||||
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
+ configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
|
||||
+ configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine 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 df5d926fb4401dd93d658fe14ae4d9d58cff68f9..b6d84fea596cfa78032151ab2f206b6b3d5dd197 100644
|
||||
index e4022494b050b68d54bac3cde87bdfc9e908859c..a4188ef831825764c0756b826651e2e7a9f99c5b 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(category = EnumConfigCategory.MISC, name = "server_mod_name")
|
||||
public class ServerModNameConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "name")
|
||||
@ConfigInfo(name = "name", comments = "Decides the server mod name shown in your F3 debug screen.")
|
||||
- public static String serverModName = "Luminol";
|
||||
+ public static String serverModName = "Lophine";
|
||||
|
||||
@ConfigInfo(name = "vanilla_spoof")
|
||||
@ConfigInfo(name = "vanilla_spoof", comments = "Ignore any plugin's modification and server mod name set in this config block, only force sending brand name of vanilla")
|
||||
public static boolean fakeVanilla = false;
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 16 Mar 2026 15:51:40 +0800
|
||||
Subject: [PATCH] Diff in auto-update patch
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
index ce01352b637547c1cf8308d56d4b3f9c48fcca70..9b5623ce1de3d68c949c3c00b966cedab3a4c986 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
@@ -16,13 +16,13 @@ import java.util.Set;
|
||||
category = EnumConfigCategory.MISC,
|
||||
name = "auto_update",
|
||||
comments = """
|
||||
- Checks GitHub Releases for newer Luminol jars on a schedule.
|
||||
- Downloads are staged under auto_update/luminol and written to auto_update/core.path,
|
||||
+ Checks GitHub Releases for newer version's jars on a schedule.
|
||||
+ Downloads are staged under auto_update/lophine and written to auto_update/core.path,
|
||||
which Hyacinthusclip can consume on the next restart.
|
||||
- If target_jar_path is set, Luminol will also try to replace that launcher jar directly."""
|
||||
+ If target_jar_path is set, server will also try to replace that launcher jar directly."""
|
||||
)
|
||||
public class AutoUpdateConfig implements IConfigModule {
|
||||
- @ConfigInfo(name = "enabled", comments = "Whether Luminol should check for updates automatically.")
|
||||
+ @ConfigInfo(name = "enabled", comments = "Whether the server should check for updates automatically.")
|
||||
public static boolean enabled = false;
|
||||
|
||||
@ConfigInfo(name = "check_times", comments = "List of daily check times in HH:mm, based on the server's local time zone.")
|
||||
@@ -33,7 +33,7 @@ public class AutoUpdateConfig implements IConfigModule {
|
||||
|
||||
@ConfigInfo(name = "target_jar_path", comments = """
|
||||
Optional launcher jar path to replace after a successful download.
|
||||
- Leave this blank to keep the downloaded jar staged in auto_update/luminol
|
||||
+ Leave this blank to keep the downloaded jar staged in auto_update/lophine
|
||||
and let Hyacinthusclip switch to it through auto_update/core.path on restart.""")
|
||||
public static String targetJarPath = "";
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
index 94a25cd681c9352d6931edafd9ec67fd7ba8a777..d0d0cf5e5ff8d4b8efa4d9778c27267b41cf8cf8 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
@@ -35,10 +35,10 @@ public final class AutoUpdateHelper {
|
||||
private final Logger LOGGER = LogUtils.getClassLogger();
|
||||
private final Gson GSON = new Gson();
|
||||
|
||||
- private final String GITHUB_API_BASE = "https://api.github.com/repos/LuminolMC/Luminol";
|
||||
+ private final String GITHUB_API_BASE = "https://api.github.com/repos/lophineMC/lophine";
|
||||
private final Path AUTO_UPDATE_DIR = Path.of("auto_update");
|
||||
private final Path CORE_PATH_FILE = AUTO_UPDATE_DIR.resolve("core.path");
|
||||
- private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("luminol");
|
||||
+ private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("lophine");
|
||||
private final Path LATEST_PATH_FILE = LUMINOL_UPDATE_DIR.resolve("latest.path");
|
||||
private final long DAILY_TASK_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
@@ -51,13 +51,13 @@ public final class AutoUpdateHelper {
|
||||
ensureWorkingDirectories();
|
||||
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor(task -> {
|
||||
- final Thread thread = new Thread(task, "Luminol Auto Update Scheduler");
|
||||
+ final Thread thread = new Thread(task, "Lophine Auto Update Scheduler");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
if (AutoUpdateConfig.checkTimes.isEmpty()) {
|
||||
- LOGGER.warn("Luminol auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
+ LOGGER.warn("Lophine auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,14 +95,14 @@ public final class AutoUpdateHelper {
|
||||
|
||||
private void checkForUpdatesSafely() {
|
||||
if (!UPDATE_RUNNING.compareAndSet(false, true)) {
|
||||
- LOGGER.info("A Luminol auto-update check is already running, skipping this schedule.");
|
||||
+ LOGGER.info("A Lophine auto-update check is already running, skipping this schedule.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
checkForUpdates();
|
||||
} catch (Exception e) {
|
||||
- LOGGER.warn("Luminol auto-update failed.", e);
|
||||
+ LOGGER.warn("Lophine auto-update failed.", e);
|
||||
} finally {
|
||||
UPDATE_RUNNING.set(false);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final ReleaseAssetInfo latestRelease = getLatestCompatibleRelease(mcVersion, gitBranch);
|
||||
if (latestRelease == null) {
|
||||
- LOGGER.warn("No compatible Luminol release was found for Minecraft {}{}.",
|
||||
+ LOGGER.warn("No compatible Lophine release was found for Minecraft {}{}.",
|
||||
mcVersion,
|
||||
gitBranch == null ? "" : " on branch " + gitBranch
|
||||
);
|
||||
@@ -132,7 +132,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final UpdateStatus updateStatus = compareReleaseWithCurrentBuild(latestRelease.releaseCommitHash(), currentGitHash);
|
||||
if (updateStatus == UpdateStatus.UP_TO_DATE) {
|
||||
- LOGGER.info("You are already running the latest compatible Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("You are already running the latest compatible Lophine release: {}", latestRelease.tagName());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public final class AutoUpdateHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
- LOGGER.info("Found a newer Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("Found a newer Lophine release: {}", latestRelease.tagName());
|
||||
|
||||
final Path stagedJar = downloadAndStageRelease(latestRelease);
|
||||
final Path finalJarPath = tryApplyTargetJar(stagedJar);
|
||||
@@ -163,7 +163,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
if (finalJarPath.equals(stagedJar)) {
|
||||
LOGGER.info(
|
||||
- "Downloaded the latest Luminol jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
+ "Downloaded the latest Lophine jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
finalJarPath.toAbsolutePath()
|
||||
);
|
||||
} else {
|
||||
@@ -179,7 +179,7 @@ public final class AutoUpdateHelper {
|
||||
try {
|
||||
Files.createDirectories(LUMINOL_UPDATE_DIR);
|
||||
} catch (IOException e) {
|
||||
- throw new RuntimeException("Failed to create Luminol auto update directory", e);
|
||||
+ throw new RuntimeException("Failed to create Lophine auto update directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ public final class AutoUpdateHelper {
|
||||
private @NotNull HttpURLConnection openConnection(String url) throws IOException, URISyntaxException {
|
||||
final HttpURLConnection connection = (HttpURLConnection) new URI(url).toURL().openConnection();
|
||||
connection.setRequestProperty("Accept", "application/vnd.github+json");
|
||||
- connection.setRequestProperty("User-Agent", "Luminol Auto Update");
|
||||
+ connection.setRequestProperty("User-Agent", "Lophine Auto Update");
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(10000);
|
||||
return connection;
|
||||
@@ -1,30 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 26 Aug 2025 22:08:54 +0800
|
||||
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 ba360d57fd9ee2363c73863bc01b6592e59be4e5..86e6cc4c024ece5f45fb53b4cd341b1df2e8f0c7 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", directory = {"experiment", "force_the_data_command_to_be_enabled"})
|
||||
@ConfigInfo(name = "enable_data_command")
|
||||
public static boolean data = 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 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(category = EnumConfigCategory.OPTIMIZATIONS, name = "force_disable_packet_limiter_of_paper")
|
||||
public class PaperPacketLimiterConfig implements IConfigModule {
|
||||
+ @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;
|
||||
@@ -3,15 +3,12 @@ From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 13 Aug 2025 22:23:46 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/d93e9766d3797d130f66179e70a1b374c546fef7/leaves-server/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java)
|
||||
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 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981c4e34aed 100644
|
||||
index a5df7e40369cf2c309f4d37fede6615f34a467e2..84d0e1a7cd687ac4ed9f1bf824ca28940c2fab1e 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 @@
|
||||
@@ -17,10 +17,98 @@
|
||||
|
||||
package org.leavesmc.leaves.util;
|
||||
|
||||
@@ -30,8 +27,9 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
|
||||
// Only the used part is retained
|
||||
// Only used part of the original code was copied
|
||||
public class ItemOverstackUtils {
|
||||
+
|
||||
+ private static final List<ItemUtil> overstackUtils = List.of(
|
||||
+ new ShulkerBox()
|
||||
+ );
|
||||
@@ -39,7 +37,7 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ public static int getItemStackMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if ((size = util.getMaxServerStackCount(stack)) != -1) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxServerStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
@@ -49,7 +47,7 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ public static int getNetworkMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if ((size = util.getMaxClientStackCount(stack)) != -1) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxClientStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
@@ -58,7 +56,7 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+
|
||||
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.tryStackItems(self, other)) {
|
||||
+ if (util.isEnabled() && util.tryStackItems(self, other)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
@@ -66,7 +64,12 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ }
|
||||
+
|
||||
+ public static boolean hasOverstackingItem() {
|
||||
+ return overstackUtils.stream().anyMatch(ItemUtil::isEnabled);
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static int getItemStackMaxCountReal(ItemStack stack) {
|
||||
@@ -103,6 +106,9 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+
|
||||
public static float getItemStackSignalStrength(int maxStackSize, ItemStack itemStack) {
|
||||
float result = (float) itemStack.getCount() / Math.min(maxStackSize, itemStack.getMaxStackSize());
|
||||
/*if (LeavesConfig.modify.oldMC.allowGrindstoneOverstacking && CurseEnchantedBook.isCursedEnchantedBook(itemStack)) { // Luminol
|
||||
@@ -28,4 +116,80 @@ public class ItemOverstackUtils {
|
||||
}*/ // Luminol
|
||||
return Math.clamp(result, 0f, 1f);
|
||||
}
|
||||
+
|
||||
@@ -110,7 +116,6 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ private interface ItemUtil {
|
||||
+ boolean isEnabled();
|
||||
+
|
||||
@@ -134,7 +139,8 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ }
|
||||
+
|
||||
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
|
||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
|
||||
+ // Leaves - Paper 26.1: ItemContainerContents#stream() removed, use nonEmptyItemCopyStream()
|
||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).nonEmptyItemCopyStream().findAny().isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
@@ -145,10 +151,7 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+ @Override
|
||||
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ ItemStack selfStack = self.getItem();
|
||||
+ if (!isEnabled() ||
|
||||
+ !(selfStack.getItem() instanceof BlockItem blockItem) ||
|
||||
+ !(blockItem.getBlock() instanceof ShulkerBoxBlock)
|
||||
+ ) {
|
||||
+ if (!(selfStack.getItem() instanceof BlockItem blockItem) || !(blockItem.getBlock() instanceof ShulkerBoxBlock)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
@@ -177,7 +180,7 @@ index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxServerStackCount(ItemStack stack) {
|
||||
+ if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
|
||||
+ if (stack.getItem() instanceof BlockItem bi &&
|
||||
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
||||
+ return ContainerExpansionConfig.shulkerCount;
|
||||
+ }
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 18 Feb 2026 00:15:08 +0800
|
||||
Subject: [PATCH] Leaves: Fakeplayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
index 0a20c6f03625391201e5ced167707e54ed27daa1..2872b22e44cba48442c526f0a53e1fc6c5ce760f 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
@@ -46,6 +46,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
|
||||
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
|
||||
+
|
||||
this.waypoints.add(waypoint);
|
||||
|
||||
for (ServerPlayer toCreateFor : this.trackingPlayers) {
|
||||
@@ -101,7 +107,13 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
|
||||
scheduleIfOffTarget(player, () -> {
|
||||
this.trackingPlayers.add(player);
|
||||
|
||||
- for (WaypointTransmitter transmitter : this.waypoints) {
|
||||
+ // Leaves start - fakeplayer
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
+ for (WaypointTransmitter transmitter : this.waypoints) {
|
||||
this.createConnection(player, transmitter);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 8f0548908a9e43ce29c4476f2707f6898e540aec..8b7c66785a06eb4782de0b0a9b542221d6258220 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -11,14 +11,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
private final Set<String> availableFeatures = new HashSet<>();
|
||||
|
||||
private ServerFeatureManager() {
|
||||
- if (false) { // Luminol not provide this
|
||||
- availableFeatures.addAll(Set.of(
|
||||
- FAKEPLAYER,
|
||||
- PHOTOGRAPHER,
|
||||
- BYTEBUF,
|
||||
- UPDATE_SUPPRESSION_EVENT
|
||||
- ));
|
||||
- }
|
||||
+ availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 17 May 2026 05:33:21 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 8b7c66785a06eb4782de0b0a9b542221d6258220..1f3fe7f786bb8f7c59e3a0235dcc572f3171ee6b 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -12,6 +12,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
|
||||
private ServerFeatureManager() {
|
||||
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
-60
@@ -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() {
|
||||
+18
-18
@@ -1,35 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 12 Jun 2025 04:44:24 +0800
|
||||
Subject: [PATCH] I18n support
|
||||
Subject: [PATCH] Server I18n
|
||||
|
||||
|
||||
diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java
|
||||
index 7b9e2a1a208b46a69c16e6afd8b502259893574f..c300ae4363298fecef8fa9bf739f01c0a11e145f 100644
|
||||
index 49c7f8194be8222e329fc3215a6aa6db0b221b11..c6c968d28e0d14a4c50e66bdd5176a000944b707 100644
|
||||
--- a/net/minecraft/locale/Language.java
|
||||
+++ b/net/minecraft/locale/Language.java
|
||||
@@ -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);
|
||||
@@ -37,6 +37,7 @@ public abstract class Language {
|
||||
Map<String, String> loadedData = new HashMap<>();
|
||||
BiConsumer<String, String> output = loadedData::put;
|
||||
parseTranslations(output, "/assets/minecraft/lang/en_us.json");
|
||||
+ fun.bm.lophine.utils.ServerI18nUtil.loadLophineI18nDefault(output); // Lophine - Server I18n
|
||||
deprecatedInfo.applyToMap(loadedData);
|
||||
final Map<String, String> storage = Map.copyOf(loadedData);
|
||||
return new Language() {
|
||||
@@ -65,7 +66,7 @@ public abstract class Language {
|
||||
@@ -66,7 +67,7 @@ public abstract class Language {
|
||||
};
|
||||
}
|
||||
|
||||
- private static void parseTranslations(BiConsumer<String, String> output, String languagePath) {
|
||||
+ public static void parseTranslations(BiConsumer<String, String> output, String languagePath) { // Lophine - private -> public
|
||||
try (InputStream resourceAsStream = Language.class.getResourceAsStream(languagePath)) {
|
||||
loadFromJson(resourceAsStream, output);
|
||||
- private static void parseTranslations(final BiConsumer<String, String> output, final String path) {
|
||||
+ public static void parseTranslations(final BiConsumer<String, String> output, final String path) { // Lophine - private -> public
|
||||
try (InputStream stream = Language.class.getResourceAsStream(path)) {
|
||||
loadFromJson(stream, output);
|
||||
} catch (JsonParseException | IOException var7) {
|
||||
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
|
||||
index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442dad2db19b 100644
|
||||
index 5b46b224bb0fea3a7e0f721ce9770657ffe0c71d..44d594da98615a8bbfb2560e0a63d2e7aab3cc7e 100644
|
||||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -155,6 +155,8 @@ public class Main {
|
||||
@@ -154,6 +154,8 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442d
|
||||
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
|
||||
if (awtException != null) {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index c93feb64b6088a4878fcdb6e7c733a5f37e9385b..79c911003c7b1c3d94e7e9d3974eeadcc16bde3a 100644
|
||||
index 3707b03b6d7ebdf47a38f4feff5b738eb41f38e1..1bc1e9a77dca7acfe5f989f6439f185d0d2e20a6 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
@@ -283,6 +283,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // Luminol - load config file
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 26 Aug 2025 02:55:23 +0800
|
||||
Subject: [PATCH] Add config to allow generation of end void rings
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/DensityFunctions.java b/net/minecraft/world/level/levelgen/DensityFunctions.java
|
||||
index 04527a5c65ad630f794fed9071d485aedd02257a..57e4c6c60f7d012a9de411b07d000f3504c27e6b 100644
|
||||
--- a/net/minecraft/world/level/levelgen/DensityFunctions.java
|
||||
+++ b/net/minecraft/world/level/levelgen/DensityFunctions.java
|
||||
@@ -528,7 +528,7 @@ public final class DensityFunctions {
|
||||
int i1 = z / 2;
|
||||
int i2 = x % 2;
|
||||
int i3 = z % 2;
|
||||
- float f = 100.0F - Mth.sqrt((long)x * (long)x + (long)z * (long)z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
|
||||
+ float f = fun.bm.lophine.config.modules.fixes.EndVoidRingsConfig.enabled ? 100.0F - Mth.sqrt(x * x + z * z) * 8.0F : 100.0F - Mth.sqrt((long)x * (long)x + (long)z * (long)z) * 8.0F; // Paper - cast ints to long to avoid integer overflow // Lophine - customize end void rings generation
|
||||
f = Mth.clamp(f, -100.0F, 80.0F);
|
||||
|
||||
NoiseCache cache = noiseCache.get().computeIfAbsent(noise, noiseKey -> new NoiseCache()); // Paper - Perf: Optimize end generation
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
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 35c1b7f40563823401ca204ec41ef57220b5ad55..f993a4de22558e7b9598aa7500cd3cc1225e4c5b 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2472,6 +2472,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.reloadResources(packsToEnable, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
}
|
||||
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ public void saveDatapacks(Collection<String> selectedPacks) {
|
||||
+ this.packRepository.setSelected(selectedPacks, 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(
|
||||
final Collection<String> packsToEnable, final io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause
|
||||
) {
|
||||
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
|
||||
index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..04fa1c5bb1c0b025a56941aae7d2151d1087e257 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(Commands.LEVEL_GAMEMASTERS))
|
||||
- /*.then( // Luminol - Add back read-only datapack command
|
||||
+ .then(
|
||||
Commands.literal("enable")
|
||||
.then(
|
||||
Commands.argument("name", StringArgumentType.string())
|
||||
@@ -145,11 +145,11 @@ public class DataPackCommand {
|
||||
.suggests(SELECTED_PACKS)
|
||||
.executes(c -> disablePack(c.getSource(), getPack(c, "name", false)))
|
||||
)
|
||||
- )*/ // Luminol - Add back read-only datapack command
|
||||
+ )
|
||||
.then(
|
||||
Commands.literal("list")
|
||||
.executes(c -> listPacks(c.getSource()))
|
||||
- //.then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource()))) // Luminol - Add back read-only datapack command
|
||||
+ .then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource()))) // Luminol - Add back read-only datapack command
|
||||
.then(Commands.literal("enabled").executes(c -> listEnabledPacks(c.getSource())))
|
||||
)
|
||||
.then(
|
||||
@@ -235,7 +235,7 @@ public class DataPackCommand {
|
||||
}
|
||||
|
||||
private static int listPacks(final CommandSourceStack source) {
|
||||
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
|
||||
+ return listEnabledPacks(source) + listAvailablePacks(source);
|
||||
}
|
||||
|
||||
private static int listAvailablePacks(final CommandSourceStack source) {
|
||||
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
|
||||
index 80fef4277b9e986c17a4cb895e130726bdb63229..4bed8d0432508cbe5c0d1fc7d68052ec2af7260f 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(final Collection<String> selectedPacks, final CommandSourceStack source) {
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ source.getServer().saveDatapacks(selectedPacks);
|
||||
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
|
||||
+ if (false) {
|
||||
source.getServer().reloadResources(selectedPacks, 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(final PackRepository packRepository, final WorldData worldData, final Collection<String> currentPacks) {
|
||||
+53
-53
@@ -3,15 +3,15 @@ From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 20 Feb 2025 01:00:28 +0800
|
||||
Subject: [PATCH] Purpur: Barrels and enderchests 6 rows
|
||||
|
||||
Co-authored by: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
||||
Co-authored by: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b9764c051 100644
|
||||
index 63b81f30b8d813a7986ae72842fdc2d3097fa103..527c495bb4f6007aee760b99cc0e9aa589931f4b 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1087,6 +1087,10 @@ public abstract class PlayerList {
|
||||
@@ -961,6 +961,10 @@ public abstract class PlayerList {
|
||||
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
|
||||
this.server.getCommands().sendCommands(player);
|
||||
} // Paper - Add sendOpLevel API
|
||||
@@ -23,11 +23,11 @@ index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b
|
||||
|
||||
// Paper start - whitelist verify event / login event
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 09b549fa9568aa1ae13b1b975db14a6268fdaa46..6c933c27ce155eb516a9ede96fb2c3bd19251bfa 100644
|
||||
index c157aa170d5879206810f4852a96120396b69db7..b9cc33198efceb75dfef333c018b1296944451cb 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -219,6 +219,7 @@ public abstract class Player extends LivingEntity {
|
||||
private int currentImpulseContextResetGraceTime = 0;
|
||||
@@ -174,6 +174,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
public float hurtDir;
|
||||
public boolean affectsSpawning = true; // Paper - Affects Spawning API
|
||||
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
|
||||
+ public int enderChestSlotCount = -1; // Purpur - Barrels and enderchests 6 rows
|
||||
@@ -35,42 +35,42 @@ index 09b549fa9568aa1ae13b1b975db14a6268fdaa46..6c933c27ce155eb516a9ede96fb2c3bd
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
|
||||
index 0fffa384f928ab84451331380968fb4650eafe26..d84a10396395939149da88bcb01be59e220c340e 100644
|
||||
index e77bfcd31cdcfd5836dc5db561e3fe2bc552a4b1..297657f38ce4c4bfa58cca27d440595246200d94 100644
|
||||
--- a/net/minecraft/world/inventory/ChestMenu.java
|
||||
+++ b/net/minecraft/world/inventory/ChestMenu.java
|
||||
@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, 6);
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, inventory, 6);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu oneRow(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x1, syncId, playerInventory, inventory, 1);
|
||||
+ public static ChestMenu oneRow(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 1);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu twoRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x2, syncId, playerInventory, inventory, 2);
|
||||
+ public static ChestMenu twoRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 2);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu threeRows(int containerId, Inventory playerInventory, Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x3, containerId, playerInventory, container, 3);
|
||||
public static ChestMenu threeRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 3);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu fourRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x4, syncId, playerInventory, inventory, 4);
|
||||
+ public static ChestMenu fourRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 4);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu fiveRows(int syncId, Inventory playerInventory, Container inventory) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x5, syncId, playerInventory, inventory, 5);
|
||||
+ public static ChestMenu fiveRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 5);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu sixRows(int containerId, Inventory playerInventory, Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6);
|
||||
public static ChestMenu sixRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, inventory, container, 6);
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
index 51148b7b95c93a9e25da70ac9275c63f1458d84c..dba8acfcacfe9a7b7e0fb9943fba49468214616e 100644
|
||||
index 4df3a32faf85595372f4b250482d852c985ea3ab..101b3711bfb98888837ebed323561cac6efb274d 100644
|
||||
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
@@ -26,11 +26,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
|
||||
@@ -90,38 +90,38 @@ index 51148b7b95c93a9e25da70ac9275c63f1458d84c..dba8acfcacfe9a7b7e0fb9943fba4946
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) {
|
||||
this.activeChest = enderChestBlockEntity;
|
||||
public void setActiveChest(final EnderChestBlockEntity activeChest) {
|
||||
this.activeChest = activeChest;
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..cef29289b7bc7fdf9613c0cd52f2bf4f715f288d 100644
|
||||
index 24a2c411da0ebbb7f97d621bb76ff686621f9aae..a9f511a549681a76a962855c26b9af5980f36df7 100644
|
||||
--- a/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
@@ -85,8 +85,14 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
enderChestInventory.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
|
||||
@@ -88,7 +88,15 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
// Paper start - Fix InventoryOpenEvent cancellation - moved up;
|
||||
container.setActiveChest(enderChest); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
|
||||
if (level instanceof ServerLevel serverLevel && player.openMenu(
|
||||
new SimpleMenuProvider(
|
||||
- (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
|
||||
- )
|
||||
+ (containerId, playerInventory, player1) -> switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(containerId, playerInventory, enderChestInventory);
|
||||
+ case 5 -> ChestMenu.fiveRows(containerId, playerInventory, enderChestInventory);
|
||||
+ case 4 -> ChestMenu.fourRows(containerId, playerInventory, enderChestInventory);
|
||||
+ case 2 -> ChestMenu.twoRows(containerId, playerInventory, enderChestInventory);
|
||||
+ case 1 -> ChestMenu.oneRow(containerId, playerInventory, enderChestInventory);
|
||||
+ default -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory);
|
||||
- new SimpleMenuProvider((containerId, inventory, p) -> ChestMenu.threeRows(containerId, inventory, container), CONTAINER_TITLE)
|
||||
+ new SimpleMenuProvider(
|
||||
+ (containerId, inventory, p) -> switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(containerId, inventory, container);
|
||||
+ case 5 -> ChestMenu.fiveRows(containerId, inventory, container);
|
||||
+ case 4 -> ChestMenu.fourRows(containerId, inventory, container);
|
||||
+ case 2 -> ChestMenu.twoRows(containerId, inventory, container);
|
||||
+ case 1 -> ChestMenu.oneRow(containerId, inventory, container);
|
||||
+ default -> ChestMenu.threeRows(containerId, inventory, container);
|
||||
+ }, CONTAINER_TITLE) // Purpur - Barrels and enderchests 6 rows
|
||||
).isPresent()) {
|
||||
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
|
||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495ebd87b5f 100644
|
||||
index 61e39a18c0fba22699750e5c0187d19a0433b9a2..98c48426fcbb4aeba479e87ab27b03e17b50d7f5 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -56,7 +56,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -60,7 +60,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
private static final Component DEFAULT_NAME = Component.translatable("container.barrel");
|
||||
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
|
||||
@@ -135,9 +135,9 @@ index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
@Override
|
||||
protected void onOpen(Level level, BlockPos pos, BlockState state) {
|
||||
@@ -108,7 +118,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
{
|
||||
Objects.requireNonNull(BarrelBlockEntity.this);
|
||||
@@ -123,7 +133,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
@@ -155,19 +155,19 @@ index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,7 +148,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -144,7 +163,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Override
|
||||
protected AbstractContainerMenu createMenu(int id, Inventory player) {
|
||||
- return ChestMenu.threeRows(id, player, this);
|
||||
protected AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
||||
- return ChestMenu.threeRows(containerId, inventory, this);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ return switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(id, player, this);
|
||||
+ case 5 -> ChestMenu.fiveRows(id, player, this);
|
||||
+ case 4 -> ChestMenu.fourRows(id, player, this);
|
||||
+ case 2 -> ChestMenu.twoRows(id, player, this);
|
||||
+ case 1 -> ChestMenu.oneRow(id, player, this);
|
||||
+ default -> ChestMenu.threeRows(id, player, this);
|
||||
+ case 6 -> ChestMenu.sixRows(containerId, inventory, this);
|
||||
+ case 5 -> ChestMenu.fiveRows(containerId, inventory, this);
|
||||
+ case 4 -> ChestMenu.fourRows(containerId, inventory, this);
|
||||
+ case 2 -> ChestMenu.twoRows(containerId, inventory, this);
|
||||
+ case 1 -> ChestMenu.oneRow(containerId, inventory, this);
|
||||
+ default -> ChestMenu.threeRows(containerId, inventory, this);
|
||||
+ };
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
+25
-25
@@ -1,55 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 3 Aug 2025 14:26:37 +0800
|
||||
Subject: [PATCH] Disable some check for operators
|
||||
Subject: [PATCH] Add config to disable some check for operators
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index f06b9d8ad9512d35f3f460eb77c869690321c67f..e17f9629369f8653b484b4cc71de4874b5faa4d6 100644
|
||||
index aa9e99358e5f3a5d07d9902708bcfa6255d26b97..47beff71ed33e7fbd6fe6cd47aa955233af41f04 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -367,7 +367,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -399,7 +399,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.tickCount++;
|
||||
this.knownMovePacketCount = this.receivedMovePacketCount;
|
||||
if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) {
|
||||
- if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player)) {
|
||||
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingPlayer, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause
|
||||
return;
|
||||
@@ -386,7 +386,7 @@ public class ServerGamePacketListenerImpl
|
||||
return true;
|
||||
@@ -418,7 +418,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.vehicleLastGoodY = this.lastVehicle.getY();
|
||||
this.vehicleLastGoodZ = this.lastVehicle.getZ();
|
||||
if (this.clientVehicleIsFloating && this.lastVehicle.getControllingPassenger() == this.player) {
|
||||
- if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle)) {
|
||||
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingVehicle, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause
|
||||
return;
|
||||
@@ -644,7 +644,7 @@ public class ServerGamePacketListenerImpl
|
||||
d5 = d2 - rootVehicle.getZ();
|
||||
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
boolean flag1 = false;
|
||||
- if (!me.earthme.luminol.config.modules.misc.DisableMovedWronglyThreshold.enabled && d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableMovedWronglyThreshold.enabled && d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Spigot // Lophine - disable move check for operator
|
||||
flag1 = true; // Paper - diff on change, this should be moved wrongly
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
|
||||
return true;
|
||||
@@ -671,7 +671,7 @@ public class ServerGamePacketListenerImpl
|
||||
zDist = targetZ - vehicle.getZ();
|
||||
movedDist = xDist * xDist + yDist * yDist + zDist * zDist;
|
||||
boolean fail = false;
|
||||
- if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot // Leaves - disable can
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Spigot // Leaves - disable can // Lophine - disable move check for operator
|
||||
fail = true;
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", vehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(movedDist));
|
||||
}
|
||||
@@ -1540,7 +1540,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1603,7 +1603,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
toX, toY, toZ, toYaw, toPitch, true);
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
- if (!event.isAllowed()) {
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
|
||||
if (event.getLogWarning()) {
|
||||
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5);
|
||||
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), xDist, yDist, zDist);
|
||||
}
|
||||
@@ -1618,7 +1618,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1682,7 +1682,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY,
|
||||
toX, toY, toZ, toYaw, toPitch, true);
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
- if (!event.isAllowed()) {
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
|
||||
movedWrongly = true;
|
||||
if (event.getLogWarning())
|
||||
// Paper end
|
||||
-59
@@ -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 75027e73859c955a54034640f905cb5d91a6a2f4..b4b3ff86f7c4afb94fc4da5133746391a078a7fb 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/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"));
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 16 Jan 2026 02:34:43 +0800
|
||||
Subject: [PATCH] Add config to enable save-all command
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index 3416445888860746c15a978f401c87245609b64a..fc6402dd0a47f5b2792aa8a21703bfee18dd2388 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -359,6 +359,8 @@ public final class RegionizedServer {
|
||||
// tick player ping sample
|
||||
this.tickPlayerSample();
|
||||
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.checkTimeout(); // Lophine - save-all fix
|
||||
+
|
||||
// tick worlds
|
||||
for (final ServerLevel world : this.worlds) {
|
||||
this.globalTick(world, tickCount);
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegions.java b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
index 02c004bc7f9a0203523ce4b27cd766d6bdc478c0..3d86e21198f2888422330b6f7c27712f40a6aabc 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegions.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
@@ -190,6 +190,8 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
|
||||
public final ThreadedRegionizer.ThreadedRegion<TickRegionData, TickRegionSectionData> region;
|
||||
public final ServerLevel world;
|
||||
|
||||
+ public long lastSavedTime = 0; // Lophine - save-all fix
|
||||
+
|
||||
// generic regionised data
|
||||
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index bcb1a5ec17269529ef0f9556043a7183df846eab..4503e62a72e67d35db5b091c91e903058157bdbd 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -295,7 +295,11 @@ public class Commands {
|
||||
PardonCommand.register(this.dispatcher);
|
||||
PardonIpCommand.register(this.dispatcher);
|
||||
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
- //SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ // Lophine start - Add a config to enable save all command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.saveAll) {
|
||||
+ SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable save all command
|
||||
SaveOffCommand.register(this.dispatcher);
|
||||
SaveOnCommand.register(this.dispatcher);
|
||||
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index f993a4de22558e7b9598aa7500cd3cc1225e4c5b..82315368d5580563fc77548f22a65d04ec73b622 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1683,6 +1683,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Folia start - region threading
|
||||
public void tickServer(final long startTime, final long scheduledEnd, final long targetBuffer,
|
||||
final io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
|
||||
+ // Lophine start - save-all fix
|
||||
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
|
||||
+ }
|
||||
+ // Lophine end - save-all fix
|
||||
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||
// Folia end - region threading
|
||||
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
index bc6d01996dde0870f6ebbda14176352777938a0c..8314d239435debf7aff947b7dd3bab83e3c80dc6 100644
|
||||
--- a/net/minecraft/server/commands/SaveAllCommand.java
|
||||
+++ b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
@@ -21,7 +21,9 @@ public class SaveAllCommand {
|
||||
}
|
||||
|
||||
private static int saveAll(final CommandSourceStack source, final boolean flush) throws CommandSyntaxException {
|
||||
- source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
+ // Lophine start - save all
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.preSaveAll(source, flush);
|
||||
+/* source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
MinecraftServer server = source.getServer();
|
||||
boolean success = server.saveEverything(true, flush, true);
|
||||
if (!success) {
|
||||
@@ -29,6 +31,12 @@ public class SaveAllCommand {
|
||||
} else {
|
||||
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
|
||||
return 1;
|
||||
- }
|
||||
+ }*/
|
||||
+ return 1;
|
||||
}
|
||||
+
|
||||
+ public static SimpleCommandExceptionType getErrorFailed() {
|
||||
+ return ERROR_FAILED;
|
||||
+ }
|
||||
+ // Lophine end - save all
|
||||
}
|
||||
+17
-16
@@ -5,24 +5,24 @@ Subject: [PATCH] Add config to enable cross region damage trace
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 11e6197dec541b28733715f0d7eaa4c7b834d632..de1263404395c28209234a556347284fa557f81c 100644
|
||||
index 6cedc129f31289eaf4e3580219fc1988c0f3c5a1..5f1fad59a26e3fe29f9000a92be5d6c4422dcd01 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1345,6 +1345,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
|
||||
killCredit.awardKillScore(this, cause);
|
||||
this.createWitherRose(killCredit);
|
||||
@@ -1464,6 +1464,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.awardStat(Stats.ENTITY_KILLED_BY.get(killer.getType()));
|
||||
killer.awardKillScore(this, source);
|
||||
this.createWitherRose(killer);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity entitylivingnew = this.getKillCreditOrigin();
|
||||
+ if (entitylivingnew != null) {
|
||||
+ this.damageTransferToAsync(entitylivingnew, cause);
|
||||
+ this.damageTransferToAsync(entitylivingnew, source);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
}
|
||||
|
||||
this.level().broadcastEntityEvent(this, (byte)3);
|
||||
@@ -1368,6 +1375,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.level().broadcastEntityEvent(this, EntityEvent.DEATH);
|
||||
@@ -1487,6 +1494,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
// Leaves end - exp fix
|
||||
|
||||
@@ -48,24 +48,24 @@ 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 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc01846eaf7 100644
|
||||
index 17483ffff6cb2a9e86db7079e7c3a9a800654c62..29919b8f3c05c8ffaf66f86e441778eeefb293b1 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
|
||||
@@ -1961,6 +1961,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
final LivingEntity killer = this.getKillCredit();
|
||||
if (killer != null) {
|
||||
killer.awardKillScore(this, damageSource);
|
||||
killer.awardKillScore(this, source);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity killernew = this.getKillCreditOrigin();
|
||||
+ if (killernew != null) {
|
||||
+ this.damageTransferToAsync(killernew, damageSource);
|
||||
+ this.damageTransferToAsync(killernew, source);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
}
|
||||
}); // Paper end
|
||||
this.postDeathDropItems(deathEvent); // Paper
|
||||
@@ -1958,6 +1965,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
@@ -1971,6 +1978,19 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
return deathEvent; // Paper
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc0
|
||||
+ private void damageTransferToAsync(LivingEntity entity, DamageSource damageSource) {
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
|
||||
+ try {
|
||||
+ if (nmsEntity.isRemoved()) return;
|
||||
+ nmsEntity.awardKillScore(this, damageSource);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
@@ -81,10 +82,10 @@ index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc0
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
protected void dropEquipment(ServerLevel level) {
|
||||
protected void dropEquipment(final ServerLevel level) {
|
||||
}
|
||||
protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
|
||||
@@ -2556,6 +2575,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
@@ -2629,6 +2649,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable function command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index af895859057ca303177ec3c8a07cf7534e62cca6..e0e9fcf3224f55f2ef31c8afca3154a5992f761b 100644
|
||||
index 4503e62a72e67d35db5b091c91e903058157bdbd..86866a9fa92d2e1ac0026e5764f459cc73e0b266 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -206,7 +206,9 @@ public class Commands {
|
||||
@@ -217,7 +217,9 @@ public class Commands {
|
||||
FillCommand.register(this.dispatcher, context);
|
||||
FillBiomeCommand.register(this.dispatcher, context);
|
||||
ForceLoadCommand.register(this.dispatcher);
|
||||
+5
-5
@@ -5,11 +5,11 @@ Subject: [PATCH] Add config to enable scoreboard command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index e0e9fcf3224f55f2ef31c8afca3154a5992f761b..6633af3cff77bcd4bcc591c032d647b7a850dced 100644
|
||||
index 86866a9fa92d2e1ac0026e5764f459cc73e0b266..f54f6047f326189329e11338b17105f5555dde12 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -231,7 +231,11 @@ public class Commands {
|
||||
//RotateCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
@@ -244,7 +244,11 @@ public class Commands {
|
||||
RotateCommand.register(this.dispatcher);
|
||||
SayCommand.register(this.dispatcher);
|
||||
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
|
||||
- //ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
|
||||
@@ -18,6 +18,6 @@ index e0e9fcf3224f55f2ef31c8afca3154a5992f761b..6633af3cff77bcd4bcc591c032d647b7
|
||||
+ 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);
|
||||
SeedCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
|
||||
VersionCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
|
||||
SetBlockCommand.register(this.dispatcher, context);
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
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 waypoint command & bar
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc..9eee09ecc18abcc5972f65938ba8607dfeede026 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -259,7 +259,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.CommandConfig.waypoint) {
|
||||
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
WeatherCommand.register(this.dispatcher);
|
||||
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..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
|
||||
|
||||
@Override
|
||||
public void trackWaypoint(WaypointTransmitter waypoint) {
|
||||
- // Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+ this.waypoints.add(waypoint);
|
||||
+
|
||||
+ for (ServerPlayer serverPlayer : this.players) {
|
||||
+ this.createConnection(serverPlayer, waypoint);
|
||||
+ }
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,14 +57,48 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||
|
||||
public void addPlayer(ServerPlayer player) {
|
||||
// Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+ this.players.add(player);
|
||||
+
|
||||
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
||||
+ this.createConnection(player, waypointTransmitter);
|
||||
+ }
|
||||
+
|
||||
+ if (player.isTransmittingWaypoint()) {
|
||||
+ this.trackWaypoint((WaypointTransmitter)player);
|
||||
+ }
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
}
|
||||
|
||||
public void updatePlayer(ServerPlayer player) {
|
||||
// Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ 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());
|
||||
+
|
||||
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
||||
+ this.updateConnection(player, entry.getKey(), entry.getValue());
|
||||
+ }
|
||||
+
|
||||
+ for (WaypointTransmitter waypointTransmitter : set) {
|
||||
+ this.createConnection(player, waypointTransmitter);
|
||||
+ }
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
}
|
||||
|
||||
public void removePlayer(ServerPlayer player) {
|
||||
// Folia - region threading
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||
+ this.connections.row(player).values().removeIf(connection -> {
|
||||
+ connection.disconnect();
|
||||
+ return true;
|
||||
+ });
|
||||
+ this.untrackWaypoint((WaypointTransmitter)player);
|
||||
+ this.players.remove(player);
|
||||
+ // Lophine end - unsafe waypoint bar
|
||||
}
|
||||
|
||||
public void breakAllConnections() {
|
||||
@@ -0,0 +1,23 @@
|
||||
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 aed1641b4e09384d40da1ac6e66c1641ca34b063..44b06b1585e7630fa17d8dfb01f737b14efebcbc 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -287,7 +287,7 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
|
||||
ItemStack thisItemStack = this.getItem();
|
||||
ItemStack otherItemStack = other.getItem();
|
||||
if (Objects.equals(this.target, other.target) && areMergable(thisItemStack, otherItemStack)) {
|
||||
- if (otherItemStack.getCount() < thisItemStack.getCount()) {
|
||||
+ if (fun.bm.lophine.config.modules.misc.ItemEntityConfig.followTickSequenceMerge || otherItemStack.getCount() < thisItemStack.getCount()) { // Lophine - add follow Tick Sequence Merge, see Paper#13073
|
||||
merge(this, thisItemStack, other, otherItemStack);
|
||||
} else {
|
||||
merge(other, otherItemStack, this, thisItemStack);
|
||||
+25
-25
@@ -5,32 +5,32 @@ Subject: [PATCH] Add config to enable raytracing tracker
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd16792507f 100644
|
||||
index 0c0775bbb0c0ba0c37d1b884bb106b5250e94750..0dfb25ad032429a2aea7aa441dd5fd1848a6c617 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1278,7 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
double d1 = vec3_dx * vec3_dx + vec3_dz * vec3_dz; // Paper
|
||||
double d2 = d * d;
|
||||
@@ -1350,7 +1350,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
double distanceSquared = deltaToPlayerX * deltaToPlayerX + deltaToPlayerZ * deltaToPlayerZ; // Paper
|
||||
double rangeSquared = visibleRange * visibleRange;
|
||||
// Paper start - Configurable entity tracking range by Y
|
||||
- boolean flag = d1 <= d2;
|
||||
+ boolean flag = d1 <= d2 && !entity.isCulled(); // Luminol - Ray tracing entity tracker
|
||||
if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
|
||||
- boolean visibleToPlayer = distanceSquared <= rangeSquared;
|
||||
+ boolean visibleToPlayer = distanceSquared <= rangeSquared && !entity.isCulled(); // Luminol - Ray tracing entity tracker
|
||||
if (visibleToPlayer && level.paperConfig().entities.trackingRangeY.enabled) {
|
||||
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 34d802060e096c5acfbd9a66fab96c0e8c792fe1..47ef63061737f3efdb0ce7ec71a8d9c920385bb0 100644
|
||||
index 0e543348e48fdf2131dfa1460e37db238d02988c..b69698f47ccb0f1ac3eeea05a02ab9d798319b44 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;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
|
||||
+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
|
||||
@@ -167,7 +167,7 @@ public abstract class Entity
|
||||
ItemOwner,
|
||||
SlotProvider,
|
||||
DebugValueSource,
|
||||
- TypedInstance<EntityType<?>>, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
|
||||
+ TypedInstance<EntityType<?>>, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
|
||||
// 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
|
||||
@@ -6480,4 +6480,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
static boolean isLevelAtLeast(ValueInput input, int level) {
|
||||
@@ -6412,4 +6412,46 @@ public abstract class Entity
|
||||
// Paper end - Expose entity id counter
|
||||
|
||||
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
||||
@@ -78,10 +78,10 @@ index 34d802060e096c5acfbd9a66fab96c0e8c792fe1..47ef63061737f3efdb0ce7ec71a8d9c9
|
||||
+
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
|
||||
index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b706e3273 100644
|
||||
index cb0a52dc3795e1cf54069bcbe82abf7877a658b8..1440946665f41ebf534d701515f982bbbf4c9686 100644
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -1119,6 +1119,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
@@ -1252,6 +1252,9 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
|
||||
public final int passengerTickTimerId;
|
||||
public final int passengerInactiveTickTimerId;
|
||||
// Folia end - profiler
|
||||
@@ -90,12 +90,12 @@ index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b
|
||||
+ // Luminol end
|
||||
|
||||
public EntityType(
|
||||
EntityType.EntityFactory<T> factory,
|
||||
final EntityType.EntityFactory<T> factory,
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a6268fdaa46 100644
|
||||
index b9cc33198efceb75dfef333c018b1296944451cb..f6f6d21f3393a3ab79a84212b0d66d83d0e817f1 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -229,6 +229,25 @@ public abstract class Player extends LivingEntity {
|
||||
@@ -185,6 +185,25 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -119,9 +119,9 @@ index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a62
|
||||
+ }
|
||||
+ // Luminol end
|
||||
|
||||
public Player(Level level, GameProfile gameProfile) {
|
||||
public Player(final Level level, final GameProfile gameProfile) {
|
||||
super(EntityType.PLAYER, level);
|
||||
@@ -287,6 +306,26 @@ public abstract class Player extends LivingEntity {
|
||||
@@ -240,6 +259,26 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
@@ -148,8 +148,8 @@ index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a62
|
||||
this.noPhysics = this.isSpectator();
|
||||
if (this.isSpectator() || this.isPassenger()) {
|
||||
this.setOnGround(false);
|
||||
@@ -1426,6 +1465,7 @@ public abstract class Player extends LivingEntity {
|
||||
if (this.containerMenu != null && this.hasContainerOpen()) {
|
||||
@@ -1352,6 +1391,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
if (this.hasContainerOpen()) {
|
||||
this.doCloseContainer();
|
||||
}
|
||||
+ if (this.cullTask != null) this.cullTask.signalStop(); // Luminol - Ray tracing entity tracker
|
||||
@@ -1,63 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Sep 2025 13:21:30 +0800
|
||||
Subject: [PATCH] Rewrite tickCount support
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index b957585cf7cf7f845e20f59c7b355722880f3b4e..9b279d003eb9f780ed2723c98b28d9f4d6e3a281 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -412,6 +412,8 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
// Luminol end - Add tick command support
|
||||
|
||||
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
|
||||
+
|
||||
if (!this.tryMarkTicking()) {
|
||||
if (!this.cancelled.get()) {
|
||||
throw new IllegalStateException("Scheduled region should be acquirable");
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index b156b5c635f931a3d4abc0584591f90476d011a6..0c2b7aafa8ddee36d38fabd3561e6f97fce828f9 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -305,6 +305,8 @@ 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; // Lophine - reuse tick count
|
||||
+ private final ThreadLocal<Integer> lastTickCount = ThreadLocal.withInitial(() -> 0); // Lophine - reuse tick count
|
||||
|
||||
@Override
|
||||
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
|
||||
@@ -2227,9 +2229,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // Lophine start - reuse tick count
|
||||
public int getTickCount() {
|
||||
- throw new UnsupportedOperationException(); // Folia - region threading
|
||||
+ return this.tickCount;
|
||||
+ }
|
||||
+
|
||||
+ public boolean checkTickCount(int period) {
|
||||
+ return this.checkTickCount(period, this.lastTickCount.get());
|
||||
+ }
|
||||
+
|
||||
+ public boolean checkTickCount(int period, int lastTickCount) {
|
||||
+ if (this.tickCount % period == 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ int nextPeriodTick = ((lastTickCount / period) + 1) * period;
|
||||
+ return nextPeriodTick < this.tickCount;
|
||||
+ }
|
||||
+
|
||||
+ public void handleTickCount(int deltaTicks) {
|
||||
+ this.lastTickCount.set(this.getTickCount());
|
||||
+ this.tickCount += deltaTicks;
|
||||
}
|
||||
+ // Lophine end - reuse tick count
|
||||
|
||||
public int getSpawnProtectionRadius() {
|
||||
return 16;
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 19 May 2025 00:42:17 +0800
|
||||
Subject: [PATCH] Old zombie reinforcement
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
index 0008aa0ca02fc4ea67b795b3f0a0e9656233ce89..2734ffc103ee4760d3521609fdd090ab99df675b 100644
|
||||
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
@@ -331,7 +331,7 @@ public class Zombie extends Monster {
|
||||
int x = Mth.floor(this.getX());
|
||||
int y = Mth.floor(this.getY());
|
||||
int z = Mth.floor(this.getZ());
|
||||
- EntityType<? extends Zombie> type = this.getType();
|
||||
+ EntityType<? extends Zombie> type = fun.bm.lophine.config.modules.function.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement
|
||||
Zombie reinforcement = type.create(level, EntitySpawnReason.REINFORCEMENT);
|
||||
if (reinforcement == null) {
|
||||
return true;
|
||||
@@ -1,472 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 26 Jul 2025 01:11:54 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/46cccfc39cafbca1681620d03947bc3ad558327f/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
index 643797124fe5a4489d0b7419b7e600c04f283ef2..04b4100da96aad50f08e8c59200eec934e7e873d 100644
|
||||
--- a/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
+++ b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
@@ -39,11 +39,13 @@ public class ItemInput {
|
||||
public ItemStack createItemStack(int count, boolean allowOversizedStacks) throws CommandSyntaxException {
|
||||
ItemStack itemStack = new ItemStack(this.item, count);
|
||||
itemStack.applyComponents(this.components);
|
||||
- if (allowOversizedStacks && count > itemStack.getMaxStackSize()) {
|
||||
- throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (allowOversizedStacks && count > org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)) {
|
||||
+ throw ERROR_STACK_TOO_BIG.create(this.getItemName(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack));
|
||||
} else {
|
||||
return itemStack;
|
||||
}
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
public String serialize(HolderLookup.Provider levelRegistry) {
|
||||
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
|
||||
index 7ef109cb9921c25987905149616eddbd0b2f9b9c..70fc9d6c5b226211ff5964464c37e11695d5f745 100644
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -55,7 +55,7 @@ public class GiveCommand {
|
||||
private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
|
||||
ItemStack itemStack = item.createItemStack(1, false);
|
||||
final Component displayName = itemStack.getDisplayName(); // Paper - get display name early
|
||||
- int maxStackSize = itemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
int i = maxStackSize * 100;
|
||||
if (count > i) {
|
||||
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName()));
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c869690321c67f 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3079,7 +3079,7 @@ public class ServerGamePacketListenerImpl
|
||||
} else if (slot.mayPlace(cursor)) {
|
||||
if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
|
||||
int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1;
|
||||
- toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount());
|
||||
+ toPlace = Math.min(toPlace, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(clickedItem) - clickedItem.getCount()); // Leaves - item over-stack util
|
||||
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
|
||||
if (toPlace == 1) {
|
||||
action = InventoryAction.PLACE_ONE;
|
||||
@@ -3115,7 +3115,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
|
||||
if (clickedItem.getCount() >= 0) {
|
||||
- if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) {
|
||||
+ if (clickedItem.getCount() + cursor.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(cursor)) { // Leaves - item over-stack util
|
||||
// As of 1.5, this is result slots only
|
||||
action = InventoryAction.PICKUP_ALL;
|
||||
}
|
||||
@@ -3326,6 +3326,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.containerMenu.broadcastFullState();
|
||||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.broadcastCarriedItem(); // Leaves - item over-stack util - force send carried item
|
||||
}
|
||||
if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
@@ -3437,7 +3438,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
|
||||
- boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
|
||||
+ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
|
||||
// CraftBukkit start - Call click event
|
||||
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
|
||||
@@ -3479,6 +3480,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - item over-stack util - force send carried item
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else if (flag && flag2) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
|
||||
index 2afaf6a3f18af7889f4f3b35cee9bbb5e4ec01f2..da99b4bc7fe8460945070915073be141f9bd6778 100644
|
||||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable<ItemStack>, org.leavesmc.
|
||||
return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ default int getMaxStackLeaves(ItemStack stack) {
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack));
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
void setChanged();
|
||||
|
||||
boolean stillValid(Player player);
|
||||
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
|
||||
index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab630b0e54e 100644
|
||||
--- a/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/net/minecraft/world/SimpleContainer.java
|
||||
@@ -211,7 +211,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
@Override
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.items.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
}
|
||||
|
||||
private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) {
|
||||
- int maxStackSize = this.getMaxStackSize(other);
|
||||
+ int maxStackSize = this.getMaxStackLeaves(other); // Leaves - item over-stack util
|
||||
int min = Math.min(stack.getCount(), maxStackSize - other.getCount());
|
||||
if (min > 0) {
|
||||
other.grow(min);
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index fd4f1e63f980b6959fc80084651991f8f8bc6c34..e5e8c752129a6ebb0dd1315c9b8ec459be11ef07 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -283,10 +283,15 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
|
||||
|
||||
private boolean isMergable() {
|
||||
ItemStack item = this.getItem();
|
||||
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
|
||||
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item); // Paper - Alternative item-despawn-rate // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
private void tryToMerge(ItemEntity itemEntity) {
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.tryStackItems(this, itemEntity)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
ItemStack item = this.getItem();
|
||||
ItemStack item1 = itemEntity.getItem();
|
||||
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0c59f7654 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -165,10 +165,12 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) {
|
||||
+ // Leaves start - item over-stack util
|
||||
return !destination.isEmpty()
|
||||
- && destination.isStackable()
|
||||
- && destination.getCount() < this.getMaxStackSize(destination)
|
||||
+ && org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(destination)
|
||||
+ && destination.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(destination)
|
||||
&& ItemStack.isSameItemSameComponents(destination, origin); // Paper - check if itemstack is stackable first
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
// CraftBukkit start - Watch method above! :D
|
||||
@@ -181,7 +183,7 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
|
||||
- remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -190,7 +192,7 @@ public class Inventory implements Container, Nameable {
|
||||
|
||||
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
|
||||
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
|
||||
- remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -314,7 +316,7 @@ public class Inventory implements Container, Nameable {
|
||||
this.setItem(slot, item);
|
||||
}
|
||||
|
||||
- int i = this.getMaxStackSize(item) - item.getCount();
|
||||
+ int i = this.getMaxStackLeaves(item) - item.getCount(); // Leaves - item over-stack util
|
||||
int min = Math.min(count, i);
|
||||
if (min == 0) {
|
||||
return count;
|
||||
@@ -420,7 +422,7 @@ public class Inventory implements Container, Nameable {
|
||||
break;
|
||||
}
|
||||
|
||||
- int i = stack.getMaxStackSize() - this.getItem(slotWithRemainingSpace).getCount();
|
||||
+ int i = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Leaves - item over-stack util
|
||||
if (this.add(slotWithRemainingSpace, stack.split(i)) && sendPacket && this.player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.connection.send(this.createInventoryUpdatePacket(slotWithRemainingSpace));
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
index 83ccde54c625d40dc595e000c533f60aa929bd5a..6779503888e6d311758cffde582b0efbd66a33de 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
@@ -23,7 +23,7 @@ public class StackedItemContents {
|
||||
}
|
||||
|
||||
public void accountStack(ItemStack stack) {
|
||||
- this.accountStack(stack, stack.getMaxStackSize());
|
||||
+ this.accountStack(stack, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public void accountStack(ItemStack stack, int maxStackSize) {
|
||||
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a76381cee 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default void setChestVehicleItem(int slot, ItemStack stack) {
|
||||
this.unpackChestVehicleLootTable(null);
|
||||
this.getItemStacks().set(slot, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
default SlotAccess getChestVehicleSlot(final int index) {
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121ba48625a 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -295,6 +295,13 @@ public abstract class AbstractContainerMenu {
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ public void sendSingleSlot(int slotIndex, ItemStack item) {
|
||||
+ if (this.synchronizer != null) {
|
||||
+ this.synchronizer.sendSlotChange(this, slotIndex, item);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
private void updateDataSlotListeners(int slotIndex, int value) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, slotIndex, value);
|
||||
@@ -451,7 +458,7 @@ public abstract class AbstractContainerMenu {
|
||||
&& (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size())
|
||||
&& this.canDragTo(slot1)) {
|
||||
int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0;
|
||||
- int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack));
|
||||
+ int min = Math.min(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Leaves - item over-stack util
|
||||
int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min);
|
||||
count -= min1 - i2;
|
||||
// slot1.setByPlayer(itemStack.copyWithCount(min1));
|
||||
@@ -563,7 +570,7 @@ public abstract class AbstractContainerMenu {
|
||||
slot.setByPlayer(carried2);
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(carried, carried2)) {
|
||||
- Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player);
|
||||
+ Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried2) - carried2.getCount(), player); // Leaves - item over-stack util
|
||||
optional1.ifPresent(itemStack2 -> {
|
||||
carried2.grow(itemStack2.getCount());
|
||||
slot.onTake(player, itemStack2);
|
||||
@@ -625,7 +632,7 @@ public abstract class AbstractContainerMenu {
|
||||
Slot slot2 = this.slots.get(slotId);
|
||||
if (slot2.hasItem()) {
|
||||
ItemStack itemStack = slot2.getItem();
|
||||
- this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize()));
|
||||
+ this.setCarried(itemStack.copyWithCount(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack))); // Leaves - item over-stack util
|
||||
}
|
||||
} else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) {
|
||||
Slot slot2 = this.slots.get(slotId);
|
||||
@@ -660,15 +667,15 @@ public abstract class AbstractContainerMenu {
|
||||
int maxStackSize = button == 0 ? 1 : -1;
|
||||
|
||||
for (int i3 = 0; i3 < 2; i3++) {
|
||||
- for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < itemStack.getMaxStackSize(); i4 += maxStackSize) {
|
||||
+ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); i4 += maxStackSize) { // Leaves - item over-stack util
|
||||
Slot slot3 = this.slots.get(i4);
|
||||
if (slot3.hasItem()
|
||||
&& canItemQuickReplace(slot3, itemStack, true)
|
||||
&& slot3.mayPickup(player)
|
||||
&& this.canTakeItemForPickAll(itemStack, slot3)) {
|
||||
ItemStack item1 = slot3.getItem();
|
||||
- if (i3 != 0 || item1.getCount() != item1.getMaxStackSize()) {
|
||||
- ItemStack itemStack1 = slot3.safeTake(item1.getCount(), itemStack.getMaxStackSize() - itemStack.getCount(), player);
|
||||
+ if (i3 != 0 || item1.getCount() != org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item1)) { // Leaves - item over-stack util
|
||||
+ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) - itemStack.getCount(), player); // Leaves - item over-stack util
|
||||
itemStack.grow(itemStack1.getCount());
|
||||
}
|
||||
}
|
||||
@@ -770,7 +777,7 @@ public abstract class AbstractContainerMenu {
|
||||
i = endIndex - 1;
|
||||
}
|
||||
|
||||
- if (stack.isStackable()) {
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(stack)) { // Leaves - item over-stack util
|
||||
while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) {
|
||||
Slot slot = this.slots.get(i);
|
||||
ItemStack item = slot.getItem();
|
||||
@@ -871,7 +878,7 @@ public abstract class AbstractContainerMenu {
|
||||
public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) {
|
||||
boolean flag = slot == null || !slot.hasItem();
|
||||
return !flag && ItemStack.isSameItemSameComponents(stack, slot.getItem())
|
||||
- ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize()
|
||||
+ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack) // Leaves - item over-stack util
|
||||
: flag;
|
||||
}
|
||||
|
||||
@@ -879,7 +886,7 @@ public abstract class AbstractContainerMenu {
|
||||
return switch (type) {
|
||||
case 0 -> Mth.floor((float)stack.getCount() / slots.size());
|
||||
case 1 -> 1;
|
||||
- case 2 -> stack.getMaxStackSize();
|
||||
+ case 2 -> org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack); // Leaves - item over-stack util
|
||||
default -> stack.getCount();
|
||||
};
|
||||
}
|
||||
@@ -902,7 +909,7 @@ public abstract class AbstractContainerMenu {
|
||||
for (int i = 0; i < container.getContainerSize(); i++) {
|
||||
ItemStack item = container.getItem(i);
|
||||
if (!item.isEmpty()) {
|
||||
- f += (float)item.getCount() / container.getMaxStackSize(item);
|
||||
+ f += Math.clamp((float) item.getCount() / container.getMaxStackSize(item), 0f, 1f); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..1a593d5bfc4574fd071604105422cd1d395648b8 100644
|
||||
--- a/net/minecraft/world/inventory/MerchantContainer.java
|
||||
+++ b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
@@ -109,7 +109,7 @@ public class MerchantContainer implements Container {
|
||||
@Override
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.itemStacks.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
if (this.isPaymentSlot(index)) {
|
||||
this.updateSellItem();
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
|
||||
index 5ceb8964476b40db4511bec91ff13c4f522a1357..f416d7976e41a06b5a8be93485eaa233ffceda5c 100644
|
||||
--- a/net/minecraft/world/inventory/Slot.java
|
||||
+++ b/net/minecraft/world/inventory/Slot.java
|
||||
@@ -75,7 +75,7 @@ public class Slot {
|
||||
}
|
||||
|
||||
public int getMaxStackSize(ItemStack stack) {
|
||||
- return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index 33c3a5e39e8e1aa023baab76ef94f8aed481480e..a27e1d53abc2d8b8912226add33510067e10ed52 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -166,7 +166,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
@Deprecated
|
||||
@Nullable
|
||||
private Item item;
|
||||
- PatchedDataComponentMap components;
|
||||
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
|
||||
@Nullable
|
||||
private Entity entityRepresentation;
|
||||
|
||||
@@ -193,7 +193,8 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
} else {
|
||||
Holder<Item> holder = Item.STREAM_CODEC.decode(buffer);
|
||||
DataComponentPatch dataComponentPatch = codec.decode(buffer);
|
||||
- return new ItemStack(holder, varInt, dataComponentPatch);
|
||||
+ ItemStack itemStack = new ItemStack(holder, varInt, dataComponentPatch);
|
||||
+ return org.leavesmc.leaves.util.ItemOverstackUtils.decodeMaxStackSize(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,13 +203,15 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
|
||||
buffer.writeVarInt(0);
|
||||
} else {
|
||||
- buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count
|
||||
- Item.STREAM_CODEC.encode(buffer, value.getItemHolder());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ final ItemStack itemStack = org.leavesmc.leaves.util.ItemOverstackUtils.encodeMaxStackSize(value.copy());
|
||||
+ buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count
|
||||
+ Item.STREAM_CODEC.encode(buffer, itemStack.getItemHolder());
|
||||
// Paper start - adventure; conditionally render translatable components
|
||||
boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
|
||||
- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(value))) { // pass the itemstack as context to the obfuscation session
|
||||
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
|
||||
- codec.encode(buffer, value.components.asPatch());
|
||||
+ codec.encode(buffer, itemStack.components.asPatch());
|
||||
} finally {
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
|
||||
}
|
||||
@@ -303,7 +306,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
|
||||
for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) {
|
||||
int count = itemStack.getCount();
|
||||
- int maxStackSize = itemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (count > maxStackSize) {
|
||||
return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8c8a1e5d1 100644
|
||||
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
@@ -192,7 +192,7 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||
Direction direction = state.getValue(ORIENTATION).front();
|
||||
Container containerAt = HopperBlockEntity.getContainerAt(level, pos.relative(direction));
|
||||
ItemStack itemStack = stack.copy();
|
||||
- if (containerAt != null && (containerAt instanceof CrafterBlockEntity || stack.getCount() > containerAt.getMaxStackSize(stack))) {
|
||||
+ if (containerAt != null && (containerAt instanceof CrafterBlockEntity || stack.getCount() > containerAt.getMaxStackLeaves(stack))) { // Leaves - item over-stack util
|
||||
// CraftBukkit start - InventoryMoveItemEvent
|
||||
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index d7a211220d5eba7e34b9083f06f39e9527962599..cef2d6d9a42ae36d6e2a0b31685a7738d2a400cf 100644
|
||||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -411,7 +411,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
ItemStack itemStack = this.items.get(index);
|
||||
boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, stack);
|
||||
this.items.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
if (index == 0 && !flag && this.level instanceof ServerLevel serverLevel) {
|
||||
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b8f75c253 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
@@ -155,7 +155,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack stack) {
|
||||
this.getItems().set(slot, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b64e4409b0 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -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);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -770,9 +770,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
|
||||
- if (!stack.isEmpty() && stack.getCount() > destination.getMaxStackSize()) {
|
||||
+ if (!stack.isEmpty() && (stack.getCount() > destination.getMaxStackSize() || stack.getCount() > stack.getMaxStackSize())) { // Leaves - item over-stack util
|
||||
leftover = stack; // Paper - Make hoppers respect inventory max stack size
|
||||
- stack = stack.split(destination.getMaxStackSize());
|
||||
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
|
||||
}
|
||||
// Spigot end
|
||||
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - Use vanilla hopper logic
|
||||
+10
-10
@@ -5,36 +5,36 @@ Subject: [PATCH] Spawn invulnerable time
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index de1263404395c28209234a556347284fa557f81c..44f0e3a675c612e9ca2bc40cc3898bdbca0f6718 100644
|
||||
index 5f1fad59a26e3fe29f9000a92be5d6c4422dcd01..f3afab1100a35cc9ab091944de93d1f30ef040a7 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
|
||||
@@ -242,6 +242,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private int lastSentFood = -99999999;
|
||||
private boolean lastFoodSaturationZero = true;
|
||||
public int lastSentExp = -99999999;
|
||||
+ private int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
+ protected int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
|
||||
public ParticleStatus particleStatus = ParticleStatus.ALL;
|
||||
private boolean canChatColor = true;
|
||||
@@ -925,6 +926,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.tickClientLoadTimeout();
|
||||
@@ -920,6 +921,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.connection.tickClientLoadTimeout();
|
||||
this.gameMode.tick();
|
||||
this.wardenSpawnTracker.tick();
|
||||
+ if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
|
||||
if (this.invulnerableTime > 0) {
|
||||
this.invulnerableTime--;
|
||||
}
|
||||
@@ -1435,6 +1437,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
if (this.isInvulnerableTo(level, damageSource)) {
|
||||
@@ -1556,6 +1558,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
if (this.isInvulnerableTo(level, source)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // Lophine start - spawn invulnerable time
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.spawnInvulnerableTime) {
|
||||
+ if (this.spawnInvulnerableTime > 0 && !damageSource.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) {
|
||||
+ if (this.spawnInvulnerableTime > 0 && !source.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Lophine end - spawn invulnerable time
|
||||
Entity entity = damageSource.getEntity();
|
||||
Entity entity = source.getEntity();
|
||||
if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false.
|
||||
!(entity instanceof Player player && !this.canHarmPlayer(player))
|
||||
!(entity instanceof Player playerx && !this.canHarmPlayer(playerx))
|
||||
@@ -0,0 +1,466 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 26 Jul 2025 01:11:54 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/f3784ec0525069a37e9ab8921b196f5533edbd56/leaves-server/minecraft-patches/features/0118-Item-overstack-util.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
index 28aab52fb14e9086d81dd7a3fa32e7f12136d53a..1f033b970be82b0bdb4e51b6e1c5bb03170066ae 100644
|
||||
--- a/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
+++ b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
@@ -20,8 +20,10 @@ public record ItemInput(Holder<Item> item, DataComponentPatch components) {
|
||||
|
||||
public ItemStack createItemStack(final int count) throws CommandSyntaxException {
|
||||
ItemStack result = new ItemStack(this.item, count, this.components);
|
||||
- if (count > result.getMaxStackSize()) {
|
||||
- throw ERROR_STACK_TOO_BIG.create(this.item.getRegisteredName(), result.getMaxStackSize());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (count > org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(result)) {
|
||||
+ throw ERROR_STACK_TOO_BIG.create(this.item.getRegisteredName(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(result));
|
||||
+ // Leaves end - item over-stack util
|
||||
} else {
|
||||
DataResult<ItemStack> validationResult = ItemStack.validateStrict(result);
|
||||
return validationResult.getOrThrow(ERROR_MALFORMED_ITEM::create);
|
||||
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
|
||||
index c147a1acd4fd9f94c73bee69febf651ca00c28ce..f8004bf74edeabce871515fb73fa00f331941dca 100644
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -47,7 +47,7 @@ public class GiveCommand {
|
||||
|
||||
private static int giveItem(final CommandSourceStack source, final ItemInput input, final Collection<ServerPlayer> players, final int count) throws CommandSyntaxException {
|
||||
ItemStack prototypeItemStack = input.createItemStack(1);
|
||||
- int maxStackSize = prototypeItemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(prototypeItemStack); // Leaves - item over-stack util
|
||||
int maxAllowedCount = maxStackSize * 100;
|
||||
if (count > maxAllowedCount) {
|
||||
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", maxAllowedCount, prototypeItemStack.getDisplayName()));
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 47beff71ed33e7fbd6fe6cd47aa955233af41f04..8e5b79db12882432de575f2a76aa36eac6fc8f51 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3229,7 +3229,7 @@ public class ServerGamePacketListenerImpl
|
||||
} else if (slot.mayPlace(cursor)) {
|
||||
if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
|
||||
int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1;
|
||||
- toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount());
|
||||
+ toPlace = Math.min(toPlace, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(clickedItem) - clickedItem.getCount()); // Leaves - item over-stack util
|
||||
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
|
||||
if (toPlace == 1) {
|
||||
action = InventoryAction.PLACE_ONE;
|
||||
@@ -3265,7 +3265,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
|
||||
if (clickedItem.getCount() >= 0) {
|
||||
- if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) {
|
||||
+ if (clickedItem.getCount() + cursor.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(cursor)) { // Leaves - item over-stack util
|
||||
// As of 1.5, this is result slots only
|
||||
action = InventoryAction.PICKUP_ALL;
|
||||
}
|
||||
@@ -3482,6 +3482,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.containerMenu.broadcastFullState();
|
||||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.broadcastCarriedItem(); // Leaves - item over-stack util - force send carried item
|
||||
}
|
||||
if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
@@ -3593,7 +3594,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
boolean validSlot = packet.slotNum() >= 1 && packet.slotNum() <= 45;
|
||||
- boolean validData = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
|
||||
+ boolean validData = itemStack.isEmpty() || itemStack.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (drop || (validSlot && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
|
||||
// CraftBukkit start - Call click event
|
||||
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
|
||||
@@ -3635,6 +3636,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - item over-stack util - force send carried item
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else if (drop && validData) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
|
||||
index 54d99625cfec60530e8a3288871e6dc21e179b2d..2a1c1bd2e9c326b7298978cec1fe13112e670d33 100644
|
||||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -38,6 +38,12 @@ public interface Container extends Clearable, Iterable<ItemStack>, SlotProvider,
|
||||
return Math.min(this.getMaxStackSize(), itemStack.getMaxStackSize());
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ default int getMaxStackLeaves(final ItemStack stack) {
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack));
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
void setChanged();
|
||||
|
||||
boolean stillValid(Player player);
|
||||
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
|
||||
index 21f576bb39bfd78dca87606ba3a044db8e13e28e..049c6ab6472415479435f2caab0444c3cbd33902 100644
|
||||
--- a/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/net/minecraft/world/SimpleContainer.java
|
||||
@@ -193,7 +193,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.items.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
}
|
||||
|
||||
private void moveItemsBetweenStacks(final ItemStack sourceStack, final ItemStack targetStack) {
|
||||
- int maxCount = this.getMaxStackSize(targetStack);
|
||||
+ int maxCount = this.getMaxStackLeaves(targetStack); // Leaves - item over-stack util
|
||||
int diff = Math.min(sourceStack.getCount(), maxCount - targetStack.getCount());
|
||||
if (diff > 0) {
|
||||
targetStack.grow(diff);
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 44b06b1585e7630fa17d8dfb01f737b14efebcbc..679a941a2af886697fbfcbc7f21e5f4e0ec77dc3 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -280,10 +280,15 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
|
||||
|
||||
private boolean isMergable() {
|
||||
ItemStack item = this.getItem();
|
||||
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
|
||||
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item); // Paper - Alternative item-despawn-rate // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
private void tryToMerge(final ItemEntity other) {
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.tryStackItems(this, other)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
ItemStack thisItemStack = this.getItem();
|
||||
ItemStack otherItemStack = other.getItem();
|
||||
if (Objects.equals(this.target, other.target) && areMergable(thisItemStack, otherItemStack)) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index f004911c438e6f89d6e079437e3f4104d6cbacbd..a248b1d11303237ebdf7cac4fa63865287d91a10 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -166,10 +166,12 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
private boolean hasRemainingSpaceForItem(final ItemStack slotItemStack, final ItemStack newItemStack) {
|
||||
+ // Leaves start - item over-stack util
|
||||
return !slotItemStack.isEmpty()
|
||||
- && slotItemStack.isStackable()
|
||||
- && slotItemStack.getCount() < this.getMaxStackSize(slotItemStack)
|
||||
+ && org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(slotItemStack)
|
||||
+ && slotItemStack.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(slotItemStack)
|
||||
&& ItemStack.isSameItemSameComponents(slotItemStack, newItemStack); // Paper - check if itemstack is stackable first
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
// CraftBukkit start - Watch method above! :D
|
||||
@@ -182,7 +184,7 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
|
||||
- remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -191,7 +193,7 @@ public class Inventory implements Container, Nameable {
|
||||
|
||||
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
|
||||
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
|
||||
- remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -315,7 +317,7 @@ public class Inventory implements Container, Nameable {
|
||||
this.setItem(slot, itemStackInSlot);
|
||||
}
|
||||
|
||||
- int maxToAdd = this.getMaxStackSize(itemStackInSlot) - itemStackInSlot.getCount();
|
||||
+ int maxToAdd = this.getMaxStackLeaves(itemStackInSlot) - itemStackInSlot.getCount(); // Leaves - item over-stack util
|
||||
int toAdd = Math.min(count, maxToAdd);
|
||||
if (toAdd == 0) {
|
||||
return count;
|
||||
@@ -421,7 +423,7 @@ public class Inventory implements Container, Nameable {
|
||||
break;
|
||||
}
|
||||
|
||||
- int slotHasSpaceFor = itemStack.getMaxStackSize() - this.getItem(slot).getCount();
|
||||
+ int slotHasSpaceFor = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) - this.getItem(slot).getCount(); // Leaves - item over-stack util
|
||||
if (this.add(slot, itemStack.split(slotHasSpaceFor)) && shouldSendSetSlotPacket && this.player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.connection.send(this.createInventoryUpdatePacket(slot));
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
index 1ace17d8fc7e7b8b4722a1889d49233c0ec55e20..d146f02338852810679a45bff932d9d68ee86d60 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
@@ -36,7 +36,7 @@ public class StackedItemContents {
|
||||
}
|
||||
|
||||
public void accountStack(final ItemStack itemStack) {
|
||||
- this.accountStack(itemStack, itemStack.getMaxStackSize());
|
||||
+ this.accountStack(itemStack, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public void accountStack(final ItemStack itemStack, final int maxCount) {
|
||||
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index 9c9a08752b54222e8ac8d9a38c7a28a775bd1164..42716cf2c864eba50628dc64c59ab29c1d51dc9b 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -161,7 +161,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default void setChestVehicleItem(final int slot, final ItemStack itemStack) {
|
||||
this.unpackChestVehicleLootTable(null);
|
||||
this.getItemStacks().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
default @Nullable SlotAccess getChestVehicleSlot(final int slot) {
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 4a177b4e714ba52cc18024d1233c9425afb93741..fa1f7dd22959632aaa54e72c8caf13ea072e7ca7 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -294,6 +294,14 @@ public abstract class AbstractContainerMenu {
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ public void sendSingleSlot(final int slotIndex, final ItemStack item) {
|
||||
+ if (this.synchronizer != null) {
|
||||
+ this.synchronizer.sendSlotChange(this, slotIndex, item);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
private void updateDataSlotListeners(final int id, final int currentValue) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, id, currentValue);
|
||||
@@ -450,7 +458,7 @@ public abstract class AbstractContainerMenu {
|
||||
&& (this.quickcraftType == QUICKCRAFT_TYPE_CLONE || carriedItemStack.getCount() >= this.quickcraftSlots.size())
|
||||
&& this.canDragTo(slot)) {
|
||||
int carry = slot.hasItem() ? slot.getItem().getCount() : 0;
|
||||
- int maxSize = Math.min(source.getMaxStackSize(), slot.getMaxStackSize(source));
|
||||
+ int maxSize = Math.min(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(source), slot.getMaxStackSize(source)); // Leaves - item over-stack util
|
||||
int newCount = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots.size(), this.quickcraftType, source) + carry, maxSize);
|
||||
remaining -= newCount - carry;
|
||||
// slot.setByPlayer(source.copyWithCount(newCount));
|
||||
@@ -558,7 +566,7 @@ public abstract class AbstractContainerMenu {
|
||||
slotx.setByPlayer(carried);
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(clicked, carried)) {
|
||||
- Optional<ItemStack> newCarried = slotx.tryRemove(clicked.getCount(), carried.getMaxStackSize() - carried.getCount(), player);
|
||||
+ Optional<ItemStack> newCarried = slotx.tryRemove(clicked.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried) - carried.getCount(), player); // Leaves - item over-stack util
|
||||
newCarried.ifPresent(itemsTaken -> {
|
||||
carried.grow(itemsTaken.getCount());
|
||||
slotx.onTake(player, itemsTaken);
|
||||
@@ -620,7 +628,7 @@ public abstract class AbstractContainerMenu {
|
||||
Slot slotx = this.slots.get(slotIndex);
|
||||
if (slotx.hasItem()) {
|
||||
ItemStack item = slotx.getItem();
|
||||
- this.setCarried(item.copyWithCount(item.getMaxStackSize()));
|
||||
+ this.setCarried(item.copyWithCount(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item))); // Leaves - item over-stack util
|
||||
}
|
||||
} else if (containerInput == ContainerInput.THROW && this.getCarried().isEmpty() && slotIndex >= 0) {
|
||||
Slot slotx = this.slots.get(slotIndex);
|
||||
@@ -655,15 +663,15 @@ public abstract class AbstractContainerMenu {
|
||||
int step = buttonNum == 0 ? 1 : -1;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
- for (int i = start; i >= 0 && i < this.slots.size() && carried.getCount() < carried.getMaxStackSize(); i += step) {
|
||||
+ for (int i = start; i >= 0 && i < this.slots.size() && carried.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried); i += step) { // Leaves - item over-stack util
|
||||
Slot target = this.slots.get(i);
|
||||
if (target.hasItem()
|
||||
&& canItemQuickReplace(target, carried, true)
|
||||
&& target.mayPickup(player)
|
||||
&& this.canTakeItemForPickAll(carried, target)) {
|
||||
ItemStack itemStack = target.getItem();
|
||||
- if (pass != 0 || itemStack.getCount() != itemStack.getMaxStackSize()) {
|
||||
- ItemStack removed = target.safeTake(itemStack.getCount(), carried.getMaxStackSize() - carried.getCount(), player);
|
||||
+ if (pass != 0 || itemStack.getCount() != org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)) { // Leaves - item over-stack util
|
||||
+ ItemStack removed = target.safeTake(itemStack.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried) - carried.getCount(), player); // Leaves - item over-stack util
|
||||
carried.grow(removed.getCount());
|
||||
}
|
||||
}
|
||||
@@ -770,7 +778,7 @@ public abstract class AbstractContainerMenu {
|
||||
destSlot = endSlot - 1;
|
||||
}
|
||||
|
||||
- if (itemStack.isStackable()) {
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(itemStack)) { // Leaves - item over-stack util
|
||||
while (!itemStack.isEmpty() && (backwards ? destSlot >= startSlot : destSlot < endSlot)) {
|
||||
Slot slot = this.slots.get(destSlot);
|
||||
ItemStack target = slot.getItem();
|
||||
@@ -871,7 +879,7 @@ public abstract class AbstractContainerMenu {
|
||||
public static boolean canItemQuickReplace(final @Nullable Slot slot, final ItemStack itemStack, final boolean ignoreSize) {
|
||||
boolean slotIsEmpty = slot == null || !slot.hasItem();
|
||||
return !slotIsEmpty && ItemStack.isSameItemSameComponents(itemStack, slot.getItem())
|
||||
- ? slot.getItem().getCount() + (ignoreSize ? 0 : itemStack.getCount()) <= itemStack.getMaxStackSize()
|
||||
+ ? slot.getItem().getCount() + (ignoreSize ? 0 : itemStack.getCount()) <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) // Leaves - item over-stack util
|
||||
: slotIsEmpty;
|
||||
}
|
||||
|
||||
@@ -879,7 +887,7 @@ public abstract class AbstractContainerMenu {
|
||||
return switch (quickCraftingType) {
|
||||
case 0 -> Mth.floor((float)itemStack.getCount() / quickCraftSlotsSize);
|
||||
case 1 -> 1;
|
||||
- case 2 -> itemStack.getMaxStackSize();
|
||||
+ case 2 -> org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
default -> itemStack.getCount();
|
||||
};
|
||||
}
|
||||
@@ -902,7 +910,7 @@ public abstract class AbstractContainerMenu {
|
||||
for (int i = 0; i < container.getContainerSize(); i++) {
|
||||
ItemStack itemStack = container.getItem(i);
|
||||
if (!itemStack.isEmpty()) {
|
||||
- totalPercent += (float)itemStack.getCount() / container.getMaxStackSize(itemStack);
|
||||
+ totalPercent += org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackSignalStrength(container.getMaxStackSize(), itemStack); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
index e1b1a261a5f7a3702c1788daa38e7d367195382e..cb95fa63c585b1c3859bfd3e5d4d0e5dd84c7f0d 100644
|
||||
--- a/net/minecraft/world/inventory/MerchantContainer.java
|
||||
+++ b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
@@ -108,7 +108,7 @@ public class MerchantContainer implements Container {
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.itemStacks.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
if (this.isPaymentSlot(slot)) {
|
||||
this.updateSellItem();
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
|
||||
index ee86a63c8d0d4c798ad09da87598d22c0e516840..57061d97bd368bfe934157293471fd546bb105ee 100644
|
||||
--- a/net/minecraft/world/inventory/Slot.java
|
||||
+++ b/net/minecraft/world/inventory/Slot.java
|
||||
@@ -75,7 +75,7 @@ public class Slot {
|
||||
}
|
||||
|
||||
public int getMaxStackSize(final ItemStack itemStack) {
|
||||
- return Math.min(this.getMaxStackSize(), itemStack.getMaxStackSize());
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public @Nullable Identifier getNoItemIcon() {
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index fa588ab87f978b8aeaef0f1849aa532e5a4ad940..dd4a92a0ea94d16669535bde9b6728515dafe7f4 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -160,7 +160,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
private int popTime;
|
||||
@Deprecated
|
||||
private @Nullable Holder<Item> item;
|
||||
- private PatchedDataComponentMap components;
|
||||
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
|
||||
|
||||
public static DataResult<ItemStack> validateStrict(final ItemStack itemStack) {
|
||||
DataResult<?> result = validateComponents(itemStack.getComponents());
|
||||
@@ -185,7 +185,8 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
} else {
|
||||
Holder<Item> item = Item.STREAM_CODEC.decode(input);
|
||||
DataComponentPatch patch = patchCodec.decode(input);
|
||||
- return new ItemStack(item, count, patch);
|
||||
+ ItemStack stack = new ItemStack(item, count, patch);
|
||||
+ return org.leavesmc.leaves.util.ItemOverstackUtils.decodeMaxStackSize(stack); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,17 +195,20 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
if (itemStack.isEmpty() || itemStack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
|
||||
output.writeVarInt(0);
|
||||
} else {
|
||||
- output.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count
|
||||
- Item.STREAM_CODEC.encode(output, itemStack.typeHolder());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ final ItemStack encodedStack = org.leavesmc.leaves.util.ItemOverstackUtils.encodeMaxStackSize(itemStack.copy());
|
||||
+ output.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), encodedStack, encodedStack.getCount())); // Paper - potentially sanitize count
|
||||
+ Item.STREAM_CODEC.encode(output, encodedStack.typeHolder());
|
||||
// Paper start - adventure; conditionally render translatable components
|
||||
boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
|
||||
- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session
|
||||
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(encodedStack))) { // pass the itemstack as context to the obfuscation session
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
|
||||
- patchCodec.encode(output, itemStack.components.asPatch());
|
||||
+ patchCodec.encode(output, encodedStack.components.asPatch());
|
||||
} finally {
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
|
||||
}
|
||||
// Paper end - adventure; conditionally render translatable components
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
}
|
||||
};
|
||||
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
index 15ed625105539f402fb39275b292531fe388a7a0..2b97fd6af1c4956eb173b8c66c2a3efc8772a798 100644
|
||||
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
@@ -202,7 +202,7 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||
Direction direction = blockState.getValue(ORIENTATION).front();
|
||||
Container into = HopperBlockEntity.getContainerAt(level, pos.relative(direction));
|
||||
ItemStack remaining = results.copy();
|
||||
- if (into != null && (into instanceof CrafterBlockEntity || results.getCount() > into.getMaxStackSize(results))) {
|
||||
+ if (into != null && (into instanceof CrafterBlockEntity || results.getCount() > into.getMaxStackLeaves(results))) { // Leaves - item over-stack util
|
||||
// CraftBukkit start - InventoryMoveItemEvent
|
||||
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(remaining);
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index 72a258f046c67c8970c91b8da31c0e745ec1e7ae..86a13f11fa6730f85add3e2ff47781d0fbcae170 100644
|
||||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -397,7 +397,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
ItemStack oldStack = this.items.get(slot);
|
||||
boolean same = !itemStack.isEmpty() && ItemStack.isSameItemSameComponents(oldStack, itemStack);
|
||||
this.items.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
if (slot == 0 && !same && this.level instanceof ServerLevel serverLevel) {
|
||||
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
index 65ca3c97fdd60ebbdd366673c81c4375488f0cde..a7a13fb017a4c98db7639b8d672f3ad9d7814b7f 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
@@ -134,7 +134,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.getItems().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 75a8c007ba710aa6e77ba3ed9ae5f7868894629d..d036018ee64995ee754296014888ee70c0ea5ab3 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -155,7 +155,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.unpackLootTable(null);
|
||||
this.getItems().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -670,9 +670,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (current.isEmpty()) {
|
||||
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
||||
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||
- if (!itemStack.isEmpty() && itemStack.getCount() > container.getMaxStackSize()) {
|
||||
+ if (!itemStack.isEmpty() && (itemStack.getCount() > container.getMaxStackSize() || itemStack.getCount() > itemStack.getMaxStackSize())) { // Leaves - item over-stack util
|
||||
leftover = itemStack; // Paper - Make hoppers respect inventory max stack size
|
||||
- itemStack = itemStack.split(container.getMaxStackSize());
|
||||
+ itemStack = itemStack.split(Math.min(container.getMaxStackSize(), itemStack.getMaxStackSize())); // Leaves - item over-stack util
|
||||
}
|
||||
// Spigot end
|
||||
IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading
|
||||
+50
-31
@@ -1,14 +1,15 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 1 May 2025 22:43:08 +0800
|
||||
Date: Wed, 21 Jan 2026 21:28:21 +0800
|
||||
Subject: [PATCH] Add config to enable tick command
|
||||
|
||||
Because of some bug, we disabled sprint command
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839621d73d7 100644
|
||||
index fc6402dd0a47f5b2792aa8a21703bfee18dd2388..96423a1a429f4fb1c975ad10726fe0e1ff70a6ad 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -299,6 +299,11 @@ public final class RegionizedServer {
|
||||
@@ -338,6 +338,11 @@ public final class RegionizedServer {
|
||||
this.randomWalk();
|
||||
*/
|
||||
++this.tickCount;
|
||||
@@ -20,7 +21,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
||||
// expire invalid click command callbacks
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
@@ -322,6 +327,13 @@ public final class RegionizedServer {
|
||||
@@ -366,6 +371,13 @@ public final class RegionizedServer {
|
||||
this.globalTick(world, tickCount);
|
||||
}
|
||||
|
||||
@@ -34,20 +35,20 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
@@ -455,7 +467,7 @@ public final class RegionizedServer {
|
||||
@@ -513,7 +525,7 @@ public final class RegionizedServer {
|
||||
}
|
||||
|
||||
private void tickTime(final ServerLevel world, final int tickCount) {
|
||||
private void tickTime(final ServerLevel world, final long tickCount) {
|
||||
- if (world.tickTime) {
|
||||
+ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
|
||||
if (world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
|
||||
world.setDayTime(world.levelData.getDayTime() + (long)tickCount);
|
||||
}
|
||||
world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + tickCount);
|
||||
}
|
||||
}
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722880f3b4e 100644
|
||||
index 8b09834ec36f62a73e388124129afbdfa47e6c25..ce0ace6a0c6b11f124b601d97491fee102b36554 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -31,8 +31,8 @@ public final class TickRegionScheduler {
|
||||
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,17 +56,17 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
|
||||
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
|
||||
+ public static float TICK_RATE = 20; // Luminol - Add tick command support
|
||||
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Luminol - Add tick command support
|
||||
|
||||
// Folia start - watchdog
|
||||
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
|
||||
@@ -394,8 +394,23 @@ public final class TickRegionScheduler {
|
||||
static {
|
||||
@@ -525,8 +525,23 @@ public final class TickRegionScheduler {
|
||||
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
|
||||
final long tickStart = System.nanoTime();
|
||||
|
||||
- // use max(), don't assume that tickStart >= scheduledStart
|
||||
- final int tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ final int tickCount;
|
||||
+ final long tickCount;
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
|
||||
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
|
||||
@@ -74,17 +75,17 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
|
||||
+ } else {
|
||||
+ TICK_RATE = MinecraftServer.tickRateManager.tickrate();
|
||||
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
|
||||
+ tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ }
|
||||
+ } else {
|
||||
+ // use max(), don't assume that tickStart >= scheduledStart
|
||||
+ tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ }
|
||||
+ // Luminol end - Add tick command support
|
||||
|
||||
if (!this.tryMarkTicking()) {
|
||||
if (!this.cancelled.get()) {
|
||||
@@ -435,6 +450,11 @@ public final class TickRegionScheduler {
|
||||
@@ -575,6 +590,11 @@ public final class TickRegionScheduler {
|
||||
try {
|
||||
// next start isn't updated until the end of this tick
|
||||
this.tickRegion(tickCount, tickStart, scheduledEnd);
|
||||
@@ -97,10 +98,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 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc 100644
|
||||
index f54f6047f326189329e11338b17105f5555dde12..6f3143deb9e5ff17fae5920b0a4ba34e3d9545c4 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -251,7 +251,11 @@ public class Commands {
|
||||
@@ -265,7 +265,11 @@ public class Commands {
|
||||
TeleportCommand.register(this.dispatcher);
|
||||
TellRawCommand.register(this.dispatcher, context);
|
||||
//TestCommand.register(this.dispatcher, context); // Folia - region threading
|
||||
@@ -110,27 +111,27 @@ index 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc
|
||||
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
TimeCommand.register(this.dispatcher);
|
||||
TimeCommand.register(this.dispatcher, context);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index b4b3ff86f7c4afb94fc4da5133746391a078a7fb..b156b5c635f931a3d4abc0584591f90476d011a6 100644
|
||||
index 82315368d5580563fc77548f22a65d04ec73b622..8dcd684189d953aabddc4f62a3ecc5807c949ce6 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
private String serverId;
|
||||
@@ -283,7 +283,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
private @Nullable String serverId;
|
||||
public MinecraftServer.ReloadableResources resources;
|
||||
private final StructureTemplateManager structureTemplateManager;
|
||||
- private final ServerTickRateManager tickRateManager;
|
||||
+ public static ServerTickRateManager tickRateManager; // Luminol - Add tick command support
|
||||
private final ServerDebugSubscribers debugSubscribers = new ServerDebugSubscribers(this);
|
||||
protected WorldData worldData;
|
||||
public PotionBrewing potionBrewing;
|
||||
private FuelValues fuelValues;
|
||||
private LevelData.RespawnData effectiveRespawnData = LevelData.RespawnData.DEFAULT;
|
||||
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
|
||||
index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c60d14fd87 100644
|
||||
index 8d0f810100a4eac65831913feeb9a9eeb0e6006a..afcab27006558f5d379df723968a612c1cadba60 100644
|
||||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -105,7 +105,7 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
return false;
|
||||
} else if (this.remainingSprintTicks > 0L) {
|
||||
this.sprintTickStartTime = System.nanoTime();
|
||||
@@ -139,7 +140,7 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c6
|
||||
return true;
|
||||
} else {
|
||||
this.finishTickSprint();
|
||||
@@ -113,6 +113,12 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +154,7 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c6
|
||||
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
|
||||
index 126685fb266692082b432ed297a499149e921dfb..9d8f6025c420e651611da17e77a362c738228b72 100644
|
||||
index 2dd0a8f2399a83b90356fcf0777bd1aec8eef5a9..c3dcfb633877ef230ab48a455ad4f5a1d601ba48 100644
|
||||
--- a/net/minecraft/server/commands/TickCommand.java
|
||||
+++ b/net/minecraft/server/commands/TickCommand.java
|
||||
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
|
||||
@@ -164,4 +165,22 @@ index 126685fb266692082b432ed297a499149e921dfb..9d8f6025c420e651611da17e77a362c7
|
||||
+ public static final float MAX_TICKRATE = 10000.0F; // Luminol - Add tick command support
|
||||
private static final String DEFAULT_TICKRATE = String.valueOf(20);
|
||||
|
||||
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
@@ -40,7 +40,7 @@ public class TickCommand {
|
||||
.executes(c -> step(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
|
||||
)
|
||||
)
|
||||
- .then(
|
||||
+/* .then(
|
||||
Commands.literal("sprint")
|
||||
.then(Commands.literal("stop").executes(c -> stopSprinting(c.getSource())))
|
||||
.then(
|
||||
@@ -48,7 +48,7 @@ public class TickCommand {
|
||||
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{"60s", "1d", "3d"}, b))
|
||||
.executes(c -> sprint(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
|
||||
)
|
||||
- )
|
||||
+ )*/
|
||||
.then(Commands.literal("unfreeze").executes(c -> setFreeze(c.getSource(), false)))
|
||||
.then(Commands.literal("freeze").executes(c -> setFreeze(c.getSource(), true)))
|
||||
);
|
||||
@@ -1,216 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 11 Apr 2025 16:53:57 +0800
|
||||
Subject: [PATCH] Leaves: Old raid behavior
|
||||
|
||||
Co-authored by: huanli233 <392352840@qq.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/79d9ef74c2684eb49060f07e1ab31c827326c9a5/leaves-server/minecraft-patches/features/0106-Old-raid-behavior.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
index 80f17f33f670018240c854df589cf90cdeab6e70..c9af615ff9120c07787f436dbb6024e54e3a498b 100644
|
||||
--- a/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
@@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect {
|
||||
&& !serverPlayer.isSpectator()
|
||||
&& level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& level.isVillage(serverPlayer.blockPosition())) {
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ return level.getRaids().createOrExtendRaid(serverPlayer, serverPlayer.blockPosition()) == null;
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
Raid raidAt = level.getRaidAt(serverPlayer.blockPosition());
|
||||
if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) {
|
||||
serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier));
|
||||
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
|
||||
index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34320a4fa2 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -263,7 +263,7 @@ public class Raid {
|
||||
}
|
||||
|
||||
public boolean absorbRaidOmen(ServerPlayer player) {
|
||||
- MobEffectInstance effect = player.getEffect(MobEffects.RAID_OMEN);
|
||||
+ MobEffectInstance effect = player.getEffect(fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? MobEffects.BAD_OMEN : MobEffects.RAID_OMEN); // Leaves - old Raid Behavior
|
||||
if (effect == null) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -340,7 +340,13 @@ public class Raid {
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
- this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ this.waveSpawnPos = this.preCalcRavagerSpawnLocation(level, this.raidCooldownTicks < 100 ? 1 : 0);
|
||||
+ } else {
|
||||
+ this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
}
|
||||
|
||||
if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) {
|
||||
@@ -375,7 +381,14 @@ public class Raid {
|
||||
int i = 0;
|
||||
|
||||
while (this.shouldSpawnGroup()) {
|
||||
- BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ BlockPos blockPos;
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ blockPos = this.getRavagerSpawnLocation(level, i, 20);
|
||||
+ } else {
|
||||
+ blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
if (blockPos != null) {
|
||||
this.started = true;
|
||||
this.spawnGroup(level, blockPos);
|
||||
@@ -387,7 +400,7 @@ public class Raid {
|
||||
i++;
|
||||
}
|
||||
|
||||
- if (i > 5) {
|
||||
+ if (i > (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? 3 : 5)) { // Leaves - old FindSpawnPosition
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
|
||||
this.stop();
|
||||
break;
|
||||
@@ -683,7 +696,7 @@ public class Raid {
|
||||
int i2 = this.center.getX() + Mth.floor(Mth.cos(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f);
|
||||
int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f);
|
||||
int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3);
|
||||
- if (Mth.abs(height - this.center.getY()) <= 96) {
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - skippable
|
||||
mutableBlockPos.set(i2, height, i3);
|
||||
if (!level.isVillage(mutableBlockPos) || i <= 7) {
|
||||
int i4 = 10;
|
||||
@@ -702,6 +715,36 @@ public class Raid {
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ @Nullable
|
||||
+ private BlockPos findRandomSpawnPos(ServerLevel level, int n, int n2) {
|
||||
+ int n3 = 2 - n;
|
||||
+ BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
+ SpawnPlacementType spawnPlacementType = SpawnPlacements.getPlacementType(EntityType.RAVAGER);
|
||||
+ for (int i = 0; i < n2; ++i) {
|
||||
+ float f = level.random.nextFloat() * ((float)Math.PI * 2);
|
||||
+ int n4 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0f * (float)n3) + level.random.nextInt(5);
|
||||
+ int n5 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0f * (float)n3) + level.random.nextInt(5);
|
||||
+ int n6 = level.getHeight(Heightmap.Types.WORLD_SURFACE, n4, n5);
|
||||
+ mutableBlockPos.set(n4, n6, n5);
|
||||
+ if (level.isVillage(mutableBlockPos) && n < 2) continue;
|
||||
+ if (!level.hasChunksAt(mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10) || !level.isPositionEntityTicking(mutableBlockPos) || !spawnPlacementType.isSpawnPositionOk(level, mutableBlockPos, EntityType.RAVAGER) && (!level.getBlockState((BlockPos)mutableBlockPos.below()).is(Blocks.SNOW) || !level.getBlockState(mutableBlockPos).isAir())) continue;
|
||||
+ return mutableBlockPos;
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<BlockPos> getValidSpawnPos(ServerLevel level, int n) {
|
||||
+ for (int i = 0; i < 3; ++i) {
|
||||
+ BlockPos blockPos = this.findRandomSpawnPos(level, n, 1);
|
||||
+ if (blockPos == null) continue;
|
||||
+ return Optional.of(blockPos);
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
+
|
||||
+
|
||||
private boolean addWaveMob(ServerLevel level, int wave, Raider raider) {
|
||||
// Folia start - make raids thread-safe
|
||||
if (!this.ownsRaid(level)) {
|
||||
@@ -864,4 +907,43 @@ public class Raid {
|
||||
this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaves start - old FindSpawnPosition
|
||||
+ private BlockPos getRavagerSpawnLocation(ServerLevel serverWorld, int proximity, int tries) {
|
||||
+ int i = proximity == 0 ? 2 : 2 - proximity;
|
||||
+ BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||
+ SpawnPlacementType spawnLocation = SpawnPlacements.getPlacementType(EntityType.RAVAGER);
|
||||
+
|
||||
+ for (int j = 0; j < tries; j++) {
|
||||
+ float f = serverWorld.random.nextFloat() * (float) (Math.PI * 2);
|
||||
+ int k = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float) i + serverWorld.random.nextInt(5));
|
||||
+ int l = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float) i + serverWorld.random.nextInt(5));
|
||||
+ int m = serverWorld.getHeight(Heightmap.Types.WORLD_SURFACE, k, l);
|
||||
+ mutable.set(k, m, l);
|
||||
+
|
||||
+ if (serverWorld.isVillage(mutable) && proximity < 2) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (serverWorld.hasChunksAt(mutable.getX() - 10, mutable.getZ() - 10, mutable.getX() + 10, mutable.getZ() + 10)
|
||||
+ && serverWorld.isPositionEntityTicking(mutable)
|
||||
+ && (spawnLocation.isSpawnPositionOk(serverWorld, mutable, EntityType.RAVAGER)
|
||||
+ || serverWorld.getBlockState(mutable.below()).is(Blocks.SNOW)
|
||||
+ && serverWorld.getBlockState(mutable).isAir())
|
||||
+ ) {
|
||||
+ return mutable;
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<BlockPos> preCalcRavagerSpawnLocation(ServerLevel serverWorld, int proximity) {
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ BlockPos blockPos = this.getRavagerSpawnLocation(serverWorld, proximity, 1);
|
||||
+ if (blockPos != null) {
|
||||
+ return Optional.of(blockPos);
|
||||
+ }
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Leaves end - old FindSpawnPosition
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..2d163f3d5eb1af4d539d24c0256855bbec960de4 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -128,6 +128,43 @@ public abstract class Raider extends PatrollingMonster {
|
||||
|
||||
currentRaid.removeFromRaid(serverLevel, this, false);
|
||||
}
|
||||
+
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (this.level() instanceof ServerLevel) {
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior && !this.hasRaid()) {
|
||||
+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
+ net.minecraft.world.entity.player.Player entityhuman = null;
|
||||
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ } else if (entity instanceof net.minecraft.world.entity.animal.wolf.Wolf wolf) {
|
||||
+ LivingEntity entityliving = wolf.getOwner();
|
||||
+ if (wolf.isTame() && entityliving instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (entityhuman != null && !itemstack.isEmpty() && this.isCaptain()) {
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect = entityhuman.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ int i = 1;
|
||||
+
|
||||
+ if (mobeffect != null) {
|
||||
+ i += mobeffect.getAmplifier();
|
||||
+ entityhuman.removeEffectNoUpdate(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ } else {
|
||||
+ --i;
|
||||
+ }
|
||||
+
|
||||
+ i = net.minecraft.util.Mth.clamp(i, 0, 4);
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, i, false, false, true);
|
||||
+
|
||||
+ if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
|
||||
+ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit
|
||||
+ }
|
||||
+ this.setPatrolLeader(false);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
}
|
||||
|
||||
super.die(cause);
|
||||
@@ -0,0 +1,177 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 11 Apr 2025 16:53:57 +0800
|
||||
Subject: [PATCH] Leaves: Old raid behavior
|
||||
|
||||
Co-authored by: huanli233 <392352840@qq.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/bda7e406b995290234e33283a181e33467ceda38/leaves-server/minecraft-patches/features/0114-Old-raid-behavior.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
index f58b10c7dec0d2b7dc2b3d1198539b74d13038f3..0a838a2015526dde2cb8d9006a71610e0bf5e9dc 100644
|
||||
--- a/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
@@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect {
|
||||
&& !player.isSpectator()
|
||||
&& level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& level.isVillage(player.blockPosition())) {
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ return level.getRaids().createOrExtendRaid(player, player.blockPosition()) == null;
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
Raid raid = level.getRaidAt(player.blockPosition());
|
||||
if (raid == null || raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplification));
|
||||
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
|
||||
index 24cc4a15731edcb701596fe7051e188637457e37..5440dc0fb8bccabb65fd9681ab368ef5028e2ca9 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -268,7 +268,7 @@ public class Raid {
|
||||
}
|
||||
|
||||
public boolean absorbRaidOmen(final ServerPlayer player) {
|
||||
- MobEffectInstance effect = player.getEffect(MobEffects.RAID_OMEN);
|
||||
+ MobEffectInstance effect = player.getEffect(fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? MobEffects.BAD_OMEN : MobEffects.RAID_OMEN); // Leaves - old Raid Behavior
|
||||
if (effect == null) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -345,7 +345,13 @@ public class Raid {
|
||||
}
|
||||
|
||||
if (shouldTryToFindSpawnPos) {
|
||||
- this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ this.waveSpawnPos = this.preCalcRavagerSpawnLocation(level, this.raidCooldownTicks < 100 ? 1 : 0);
|
||||
+ } else {
|
||||
+ this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
}
|
||||
|
||||
if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) {
|
||||
@@ -400,7 +406,14 @@ public class Raid {
|
||||
int attempt = 0;
|
||||
|
||||
while (this.shouldSpawnGroup()) {
|
||||
- BlockPos spawnPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ BlockPos spawnPos;
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ spawnPos = this.getRavagerSpawnLocation(level, attempt, 20);
|
||||
+ } else {
|
||||
+ spawnPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
if (spawnPos != null) {
|
||||
this.started = true;
|
||||
this.spawnGroup(level, spawnPos);
|
||||
@@ -412,7 +425,7 @@ public class Raid {
|
||||
attempt++;
|
||||
}
|
||||
|
||||
- if (attempt > 5) {
|
||||
+ if (attempt > (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? 3 : 5)) { // Leaves - old FindSpawnPosition
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
|
||||
this.stop();
|
||||
break;
|
||||
@@ -716,7 +729,7 @@ public class Raid {
|
||||
int spawnX = this.center.getX() + Mth.floor(Mth.cos(angle) * 32.0F * howFar) + this.random.nextInt(3) * Mth.floor(howFar);
|
||||
int spawnZ = this.center.getZ() + Mth.floor(Mth.sin(angle) * 32.0F * howFar) + this.random.nextInt(3) * Mth.floor(howFar);
|
||||
int spawnY = level.getHeight(Heightmap.Types.WORLD_SURFACE, spawnX, spawnZ);
|
||||
- if (Mth.abs(spawnY - this.center.getY()) <= 96) {
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior || Mth.abs(spawnY - this.center.getY()) <= 96) { // Leaves - skippable
|
||||
spawnPos.set(spawnX, spawnY, spawnZ);
|
||||
if (!level.isVillage(spawnPos) || secondsRemaining <= 7) {
|
||||
int delta = 10;
|
||||
@@ -899,4 +912,42 @@ public class Raid {
|
||||
this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaves start - old FindSpawnPosition
|
||||
+ @Nullable
|
||||
+ private BlockPos getRavagerSpawnLocation(final ServerLevel serverWorld, final int proximity, final int tries) {
|
||||
+ int i = proximity == 0 ? 2 : 2 - proximity;
|
||||
+ BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||
+ net.minecraft.world.entity.SpawnPlacementType spawnLocation = net.minecraft.world.entity.SpawnPlacements.getPlacementType(EntityType.RAVAGER);
|
||||
+ for (int j = 0; j < tries; j++) {
|
||||
+ float f = serverWorld.getRandom().nextFloat() * (float) (Math.PI * 2);
|
||||
+ int k = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float) i + serverWorld.getRandom().nextInt(5));
|
||||
+ int l = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float) i + serverWorld.getRandom().nextInt(5));
|
||||
+ int m = serverWorld.getHeight(Heightmap.Types.WORLD_SURFACE, k, l);
|
||||
+ mutable.set(k, m, l);
|
||||
+ if (serverWorld.isVillage(mutable) && proximity < 2) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (serverWorld.hasChunksAt(mutable.getX() - 10, mutable.getZ() - 10, mutable.getX() + 10, mutable.getZ() + 10)
|
||||
+ && serverWorld.isPositionEntityTicking(mutable)
|
||||
+ && (spawnLocation.isSpawnPositionOk(serverWorld, mutable, EntityType.RAVAGER)
|
||||
+ || serverWorld.getBlockState(mutable.below()).is(net.minecraft.world.level.block.Blocks.SNOW)
|
||||
+ && serverWorld.getBlockState(mutable).isAir())
|
||||
+ ) {
|
||||
+ return mutable.immutable();
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<BlockPos> preCalcRavagerSpawnLocation(final ServerLevel serverWorld, final int proximity) {
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ BlockPos blockPos = this.getRavagerSpawnLocation(serverWorld, proximity, 1);
|
||||
+ if (blockPos != null) {
|
||||
+ return Optional.of(blockPos);
|
||||
+ }
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Leaves end - old FindSpawnPosition
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index bc2edc48ddefaab9022029f1a913a40b72e06024..1a51da9171c13711e106731c360051d183a40893 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -128,6 +128,42 @@ public abstract class Raider extends PatrollingMonster {
|
||||
|
||||
raidWhenKilled.removeFromRaid(serverLevel, this, false);
|
||||
}
|
||||
+
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ Entity killerEntity = source.getEntity();
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior && !this.hasActiveRaid()) {
|
||||
+ ItemStack itemstack = this.getItemBySlot(net.minecraft.world.entity.EquipmentSlot.HEAD);
|
||||
+ net.minecraft.world.entity.player.Player entityhuman = null;
|
||||
+ if (killerEntity instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ } else if (killerEntity instanceof net.minecraft.world.entity.animal.wolf.Wolf wolf) {
|
||||
+ LivingEntity entityliving = wolf.getOwner();
|
||||
+ if (wolf.isTame() && entityliving instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (entityhuman != null && !itemstack.isEmpty() && this.isPatrolLeader()) {
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect = entityhuman.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ int amp = 1;
|
||||
+
|
||||
+ if (mobeffect != null) {
|
||||
+ amp += mobeffect.getAmplifier();
|
||||
+ entityhuman.removeEffectNoUpdate(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ } else {
|
||||
+ --amp;
|
||||
+ }
|
||||
+
|
||||
+ amp = net.minecraft.util.Mth.clamp(amp, 0, 4);
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, amp, false, false, true);
|
||||
+
|
||||
+ if (serverLevel.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.RAIDS)) {
|
||||
+ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit
|
||||
+ }
|
||||
+ this.setPatrolLeader(false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
}
|
||||
|
||||
super.die(source);
|
||||
+16
-15
@@ -6,15 +6,15 @@ 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 e94687b3aa960f9c630f459fedc17bc01846eaf7..f4f4f886b6558d39d292a45665953f497f84be53 100644
|
||||
index 29919b8f3c05c8ffaf66f86e441778eeefb293b1..1e820f34636f415ef78cdfbed06c6952a3cf1c0b 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
|
||||
@@ -1234,6 +1234,30 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
}
|
||||
}
|
||||
|
||||
+ // Lophine Start - raid revert adapt Cross Region Damage trace
|
||||
+ public boolean addEffect(MobEffectInstance effectInstance, EntityPotionEffectEvent.Cause cause, boolean fireEvent, boolean async) {
|
||||
+ public boolean addEffect(final MobEffectInstance effectInstance, EntityPotionEffectEvent.Cause cause, boolean fireEvent, boolean async) {
|
||||
+ if (!async || ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this)) {
|
||||
+ return addEffect(effectInstance, this, cause, fireEvent);
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
@@ -24,31 +24,32 @@ index e94687b3aa960f9c630f459fedc17bc01846eaf7..f4f4f886b6558d39d292a45665953f49
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private void postToAddEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||
+ private void postToAddEffect(final MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||
+ if (entity != null)
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> {
|
||||
+ try {
|
||||
+ if (nmsEntity.isRemoved()) return;
|
||||
+ addEffect(effectInstance, nmsEntity, cause, fireEvent);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L );
|
||||
+ }, null, 1L);
|
||||
+ }
|
||||
+ // Lophine End - raid revert adapt Cross Region Damage trace
|
||||
+
|
||||
public boolean canBeAffected(MobEffectInstance effectInstance) {
|
||||
if (this.getType().is(EntityTypeTags.IMMUNE_TO_INFESTED)) {
|
||||
return !effectInstance.is(MobEffects.INFESTED);
|
||||
public boolean canBeAffected(final MobEffectInstance newEffect) {
|
||||
if (this.is(EntityTypeTags.IMMUNE_TO_INFESTED)) {
|
||||
return !newEffect.is(MobEffects.INFESTED);
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index 2d163f3d5eb1af4d539d24c0256855bbec960de4..2cc0a7b5f088c29d9343b369b6e71c8a3ebdef75 100644
|
||||
index 1a51da9171c13711e106731c360051d183a40893..7094a67959e9747b2dfa55a5f5a3e90552d35466 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -158,7 +158,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, i, false, false, true);
|
||||
net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, amp, false, false, true);
|
||||
|
||||
if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
|
||||
- entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit
|
||||
+ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true, fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled); // Lophine - raid revert adapt Cross Region Damage trace
|
||||
}
|
||||
this.setPatrolLeader(false);
|
||||
if (serverLevel.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.RAIDS)) {
|
||||
- entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit
|
||||
+ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true, fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled); // CraftBukkit // Lophine - raid revert adapt Cross Region Damage trace
|
||||
}
|
||||
this.setPatrolLeader(false);
|
||||
}
|
||||
+43
-76
@@ -1,55 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 3 Aug 2025 15:24:01 +0800
|
||||
Subject: [PATCH] Leaves: Base Protocol Core
|
||||
Subject: [PATCH] Leaves: Leaves Base Protocol Core
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch)
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/9d2bd3f7b0a48f00df7bc8c74292338ed9c3a458/leaves-server/minecraft-patches/features/0122-Leaves-Protocol-Core.patch)
|
||||
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..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(); // Leaves - protocol
|
||||
+
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644
|
||||
index e9f86409bf9351e85ed31e747d9350dbf0cc441f..1f8f4d979d8766d6ba385f74cf8fcf8eea6c56c7 100644
|
||||
--- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
+++ b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
@@ -40,13 +40,22 @@ public interface CustomPacketPayload {
|
||||
|
||||
@Override
|
||||
public void encode(B buffer, CustomPacketPayload value) {
|
||||
public void encode(final B output, final CustomPacketPayload value) {
|
||||
+ // Leaves start - protocol core
|
||||
+ if (value instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload payload) {
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.encode(buffer, payload);
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.encode(output, payload);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - protocol core
|
||||
this.writeCap(buffer, value.type(), value);
|
||||
this.writeCap(output, value.type(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomPacketPayload decode(B buffer) {
|
||||
ResourceLocation resourceLocation = buffer.readResourceLocation();
|
||||
- return (CustomPacketPayload)this.findCodec(resourceLocation).decode(buffer);
|
||||
public CustomPacketPayload decode(final B input) {
|
||||
Identifier identifier = input.readIdentifier();
|
||||
- return (CustomPacketPayload)this.findCodec(identifier).decode(input);
|
||||
+ // Leaves start - protocol core
|
||||
+ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(resourceLocation, buffer);
|
||||
+ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(resourceLocation).decode(buffer));
|
||||
+ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(identifier, input);
|
||||
+ return java.util.Objects.requireNonNullElseGet(payload, () -> (CustomPacketPayload) this.findCodec(identifier).decode(input));
|
||||
+ // Leaves end - protocol core
|
||||
}
|
||||
};
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 8dcd684189d953aabddc4f62a3ecc5807c949ce6..0bedaa20bc2cae75a48357e69740ada2380a03dd 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2037,6 +2037,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
profiler.popPush("server gui refresh");
|
||||
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(); // Leaves - protocol // Lophine - we don't have tickCount to use, remove it
|
||||
+
|
||||
if (false) for (Runnable tickable : this.tickables) { // Folia - region threading - TODO WTF is this?
|
||||
tickable.run();
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3ddc776bf9e 100644
|
||||
index cf4b5e436b8d81657d1deaa5b06645016d9dc3cc..f3af5660a377e2eb823f79ec274feaf3284761cd 100644
|
||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -57,6 +57,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -58,7 +58,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
|
||||
// Paper end - retain certain values
|
||||
+ public final GameProfile profile; // Leaves - protocol core
|
||||
|
||||
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie) {
|
||||
public ServerCommonPacketListenerImpl(final MinecraftServer server, final Connection connection, final CommonListenerCookie cookie) {
|
||||
this.server = server;
|
||||
@@ -70,6 +71,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
this.pluginMessagerChannels = cookie.channels();
|
||||
@@ -68,16 +68,16 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
|
||||
}
|
||||
|
||||
// Paper start - configuration phase API
|
||||
@@ -160,6 +162,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -143,6 +145,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
@Override
|
||||
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
|
||||
public void handleCustomPayload(final ServerboundCustomPayloadPacket packet) {
|
||||
+ // Leaves start - protocol
|
||||
+ if (packet.payload() instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload leavesPayload) {
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), leavesPayload);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.DiscardedPayload(net.minecraft.resources.ResourceLocation id, byte[] data)) {
|
||||
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.DiscardedPayload(net.minecraft.resources.Identifier id, byte[] data)) {
|
||||
+ if (org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleBytebuf(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), id, io.netty.buffer.Unpooled.wrappedBuffer(data))) {
|
||||
+ return;
|
||||
+ }
|
||||
@@ -87,7 +87,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
|
||||
// Paper start
|
||||
if (!(packet.payload() instanceof final net.minecraft.network.protocol.common.custom.DiscardedPayload discardedPayload)) {
|
||||
return;
|
||||
@@ -219,10 +233,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
@@ -202,6 +216,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
final String channel = new String(data, from, length, java.nio.charset.StandardCharsets.US_ASCII);
|
||||
if (register) {
|
||||
bridge.addChannel(channel);
|
||||
@@ -95,63 +95,30 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
|
||||
} else {
|
||||
bridge.removeChannel(channel);
|
||||
}
|
||||
- // Paper end
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -385,9 +400,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
net.minecraft.server.level.ServerPlayer player = serverGamePacketListener.player;
|
||||
org.bukkit.event.player.PlayerKickEvent.Cause cause = disconnectionDetails.disconnectionReason().orElseThrow().game().orElse(org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN);
|
||||
org.bukkit.event.player.PlayerKickEvent event = new org.bukkit.event.player.PlayerKickEvent(
|
||||
- player.getBukkitEntity(),
|
||||
- io.papermc.paper.adventure.PaperAdventure.asAdventure(disconnectionDetails.reason()),
|
||||
- rawLeaveMessage, cause
|
||||
+ player.getBukkitEntity(),
|
||||
+ io.papermc.paper.adventure.PaperAdventure.asAdventure(disconnectionDetails.reason()),
|
||||
+ rawLeaveMessage, cause
|
||||
|
||||
);
|
||||
|
||||
@@ -420,10 +435,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
private void disconnect0(DisconnectionDetails disconnectionDetails) {
|
||||
this.connection
|
||||
- .send(
|
||||
- new ClientboundDisconnectPacket(disconnectionDetails.reason()),
|
||||
- PacketSendListener.thenRun(() -> this.connection.disconnect(disconnectionDetails))
|
||||
- );
|
||||
+ .send(
|
||||
+ new ClientboundDisconnectPacket(disconnectionDetails.reason()),
|
||||
+ PacketSendListener.thenRun(() -> this.connection.disconnect(disconnectionDetails))
|
||||
+ );
|
||||
this.onDisconnect(disconnectionDetails);
|
||||
this.connection.setReadOnly();
|
||||
// CraftBukkit - Don't wait
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 4ef2816210f06082f2209c51d04aad6bb188232b..593dbcda4b497291eb1ecdc64b947a8d279f8be6 100644
|
||||
index 527c495bb4f6007aee760b99cc0e9aa589931f4b..e6987eaf6e4d36d43cee4ece3ce22d31052a2a2a 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -423,6 +423,8 @@ public abstract class PlayerList {
|
||||
//return; // Folia - region threading - must still allow the player to connect, as we must add to chunk map before handling disconnect
|
||||
}
|
||||
@@ -317,6 +317,8 @@ public abstract class PlayerList {
|
||||
//return; // Folia - region threading - must still allow the player to connect, as we must add to chunk map before handling disconnect
|
||||
}
|
||||
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
||||
+
|
||||
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
|
||||
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
@@ -605,6 +607,7 @@ public abstract class PlayerList {
|
||||
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
@@ -517,6 +519,7 @@ public abstract class PlayerList {
|
||||
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
|
||||
}
|
||||
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
|
||||
public net.kyori.adventure.text.@Nullable Component remove(final ServerPlayer player, final net.kyori.adventure.text.Component leaveMessage) {
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(player); // Leaves - protocol
|
||||
// Paper end - Fix kick event leave message not being sent
|
||||
ServerLevel serverLevel = player.level();
|
||||
ServerLevel level = player.level();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
@@ -1520,6 +1523,7 @@ public abstract class PlayerList {
|
||||
serverPlayer.connection.send(clientboundUpdateRecipesPacket);
|
||||
serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer);
|
||||
@@ -1411,6 +1414,7 @@ public abstract class PlayerList {
|
||||
player.connection.send(recipes);
|
||||
player.getRecipeBook().sendInitialRecipeBook(player);
|
||||
}
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleDataPackReload(); // Leaves - protocol core
|
||||
}
|
||||
+47
@@ -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/blob/9d2bd3f7b0a48f00df7bc8c74292338ed9c3a458/leaves-server/minecraft-patches/features/0088-Configurable-trading-with-the-void.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c380ab9f059da6219691e8bccd4f82b9ec5483b3..b2ea90b0ab461d202d492411471d2412a9c5d303 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -3158,7 +3158,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// 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 e6987eaf6e4d36d43cee4ece3ce22d31052a2a2a..168702a5ae51a2bc42c5761e13cb14008a8162c4 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -560,7 +560,7 @@ public abstract class PlayerList {
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(e -> {
|
||||
// Paper start - Fix villager boat exploit
|
||||
- if (e instanceof net.minecraft.world.entity.npc.villager.AbstractVillager villager) {
|
||||
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && e instanceof net.minecraft.world.entity.npc.villager.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 1dd82dfa739957f00d51c8b987289a002815f622..85a329565119d376139a7449e538c0d83dfb079f 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(final 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);
|
||||
}
|
||||
+8
-7
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
|
||||
index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335ec643957f 100644
|
||||
index afcab27006558f5d379df723968a612c1cadba60..ddab99a4cc70a1aa365208cb52d8d9b880cdeff6 100644
|
||||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -134,4 +134,10 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
@@ -139,4 +139,10 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
player.connection.send(ClientboundTickingStatePacket.from(this));
|
||||
player.connection.send(ClientboundTickingStepPacket.from(this));
|
||||
}
|
||||
@@ -23,14 +23,15 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
|
||||
+ // Leaves end - servux
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index eb3aef1f5198592eda5dafe84b91271e861b4135..576dde41a4b48aac9079cca902f4371a31470af3 100644
|
||||
index b2ea90b0ab461d202d492411471d2412a9c5d303..049339ae33569d627d2a00ef6cab9cad02c4c014 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
@@ -2584,6 +2584,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.server.updateEffectiveRespawnData();
|
||||
}
|
||||
|
||||
this.lastSpawnChunkRadius = i;
|
||||
// Paper end
|
||||
+
|
||||
+ org.leavesmc.leaves.protocol.servux.ServuxHudDataProtocol.refreshSpawnMetadata = true; // Leaves - servux
|
||||
}
|
||||
|
||||
public LongSet getForceLoadedChunks() {
|
||||
@Override
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 17:47:48 +0800
|
||||
Subject: [PATCH] LeavesHooks
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||
index d097b889499a8e410839e8f69d99dc9adfa2488b..b97d65b81ec4b86e00b7c06341b40dc5c02b9044 100644
|
||||
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||
@@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
-public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||
+public class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||
|
||||
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
|
||||
|
||||
+6
-6
@@ -8,14 +8,14 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e96b237749a960f2
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
|
||||
index b3e897a4afee742b5055d652ad7047a660d8ea04..33471f3d0e2cbd54eaf095c19555f8fdaeb55878 100644
|
||||
index 769dc39e11881d5f81a2405850cbcbd0842c5995..9fc97e8b01f66ada6af1fe76f4e27c9bb1a5dcfc 100644
|
||||
--- a/net/minecraft/world/level/ServerExplosion.java
|
||||
+++ b/net/minecraft/world/level/ServerExplosion.java
|
||||
@@ -729,6 +729,7 @@ public class ServerExplosion implements Explosion {
|
||||
@@ -708,6 +708,7 @@ public class ServerExplosion implements Explosion {
|
||||
public boolean shouldAffectBlocklikeEntities() {
|
||||
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
boolean flag = this.source == null || this.source.getType() != EntityType.BREEZE_WIND_CHARGE && this.source.getType() != EntityType.WIND_CHARGE;
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldExplosionDamageCalculator) flag = flag && (this.source == null || !this.source.isInWater()); // Leaves - Old MC TNT wet explosion no item damage
|
||||
return _boolean ? flag : this.blockInteraction.shouldAffectBlocklikeEntities() && flag;
|
||||
boolean mobGriefingEnabled = this.level.getGameRules().get(GameRules.MOB_GRIEFING);
|
||||
boolean isNotWindCharge = this.source == null || !this.source.is(EntityType.BREEZE_WIND_CHARGE) && !this.source.is(EntityType.WIND_CHARGE);
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldExplosionDamageCalculator) isNotWindCharge = isNotWindCharge && (this.source == null || !this.source.isInWater()); // Leaves - Old MC TNT wet explosion no item damage
|
||||
return mobGriefingEnabled ? isNotWindCharge : this.blockInteraction.shouldAffectBlocklikeEntities() && isNotWindCharge;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 19 May 2025 00:42:17 +0800
|
||||
Subject: [PATCH] Old zombie reinforcement
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 14d0758aca54d9a25e369dfa8c89c930f27946c9..1324f2c8c0d6571bac36855f08354a84e0f08b70 100644
|
||||
--- a/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -341,7 +341,7 @@ public class Zombie extends Monster {
|
||||
int floor = Mth.floor(this.getX());
|
||||
int floor1 = Mth.floor(this.getY());
|
||||
int floor2 = Mth.floor(this.getZ());
|
||||
- EntityType<? extends Zombie> type = this.getType();
|
||||
+ EntityType<? extends Zombie> type = fun.bm.lophine.config.modules.function.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement
|
||||
Zombie zombie = type.create(level, EntitySpawnReason.REINFORCEMENT);
|
||||
if (zombie == null) {
|
||||
return true;
|
||||
+2
-2
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/79d9ef74c2684eb49
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
|
||||
index 8cf3e51e12f9cf98836657e722edb23943f9e866..5fd5e9fd4e1a79dd1a9d62a5cf0c308805979420 100644
|
||||
index 837f8c56bf5d68dd8bfbeca8ae1b66be8316ddea..1098695e646c20f47bc4739034fcb69b96909667 100644
|
||||
--- a/net/minecraft/world/item/ShearsItem.java
|
||||
+++ b/net/minecraft/world/item/ShearsItem.java
|
||||
@@ -80,7 +80,10 @@ public class ShearsItem extends Item {
|
||||
@@ -17,7 +17,7 @@ index 8cf3e51e12f9cf98836657e722edb23943f9e866..5fd5e9fd4e1a79dd1a9d62a5cf0c3088
|
||||
} else {
|
||||
- return super.useOn(context);
|
||||
+ // Leaves start - shears wrench
|
||||
+ InteractionResult result = org.leavesmc.leaves.util.ShearsWrenchUtil.tryApplyRotate(context, blockState);
|
||||
+ InteractionResult result = org.leavesmc.leaves.util.ShearsWrenchUtil.tryApplyRotate(context, state);
|
||||
+ return result == null ? super.useOn(context) : result;
|
||||
+ // Leaves end - shears wrench
|
||||
}
|
||||
@@ -1,828 +0,0 @@
|
||||
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
|
||||
|
||||
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/advancements/critereon/SimpleCriterionTrigger.java b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c96afb491c 100644
|
||||
--- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
+++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
|
||||
@@ -39,6 +39,7 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
|
||||
}
|
||||
|
||||
protected void trigger(ServerPlayer player, Predicate<T> testTrigger) {
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) return; // Leaves - bot skip
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
Set<CriterionTrigger.Listener<T>> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
|
||||
if (set != null && !set.isEmpty()) {
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4beca0969 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -96,7 +96,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@Nullable
|
||||
private volatile PacketListener disconnectListener;
|
||||
@Nullable
|
||||
- private volatile PacketListener packetListener;
|
||||
+ protected volatile PacketListener packetListener; // Leaves - private -> protected
|
||||
@Nullable
|
||||
private DisconnectionDetails disconnectionDetails;
|
||||
private boolean encrypted;
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 0c2b7aafa8ddee36d38fabd3561e6f97fce828f9..e5fc1969b8af692d785214731b3f8cc47df2aa78 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -349,6 +349,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
// Folia end - regionised ticking
|
||||
|
||||
+ private org.leavesmc.leaves.bot.BotList botList; // Leaves - fakeplayer
|
||||
+
|
||||
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<>();
|
||||
@@ -1040,6 +1042,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Folia end - region threading
|
||||
|
||||
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
|
||||
@@ -1590,7 +1597,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
|
||||
- if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping
|
||||
+ if (this.playerList.getPlayerCount() == 0 && this.botList.bots.isEmpty() && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping // Leaves - fakeplayer
|
||||
this.emptyTicks++;
|
||||
} else {
|
||||
this.emptyTicks = 0;
|
||||
@@ -1914,6 +1921,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
public void tickConnection() {
|
||||
this.getConnection().tick();
|
||||
+ this.botList.networkTick(); // Leaves - fakeplayer
|
||||
}
|
||||
|
||||
private void synchronizeTime(ServerLevel level) {
|
||||
@@ -3005,6 +3013,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer
|
||||
+ protected void setBotList(org.leavesmc.leaves.bot.BotList botList) {
|
||||
+ this.botList = botList;
|
||||
+ }
|
||||
+
|
||||
+ public org.leavesmc.leaves.bot.BotList getBotList() {
|
||||
+ return botList;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
public record ReloadableResources(CloseableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable {
|
||||
@Override
|
||||
public void close() {
|
||||
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
||||
index fdeca41d40705f28864ce4443d01cd872c9d51b0..5c0e338dc1b0eb5724d10a73d6fc7975f9d2e5e5 100644
|
||||
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -167,6 +167,11 @@ public class PlayerAdvancements {
|
||||
}
|
||||
|
||||
public boolean award(AdvancementHolder advancement, String criterionKey) {
|
||||
+ // Leaves start - bot can't get advancement
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Leaves end - bot can't get advancement
|
||||
boolean flag = false;
|
||||
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
|
||||
boolean isDone = orStartProgress.isDone();
|
||||
diff --git a/net/minecraft/server/commands/BanIpCommands.java b/net/minecraft/server/commands/BanIpCommands.java
|
||||
index bb5dbfeb6915a808d6f70e332bf9f0a3f9b7d19a..62f23d47b55eb59956d69153d508b5c9ab544adf 100644
|
||||
--- a/net/minecraft/server/commands/BanIpCommands.java
|
||||
+++ b/net/minecraft/server/commands/BanIpCommands.java
|
||||
@@ -44,6 +44,12 @@ public class BanIpCommands {
|
||||
return banIp(source, username, reason);
|
||||
} else {
|
||||
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(username);
|
||||
+ // Leaves start - disable ban
|
||||
+ if (playerByName instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ // Leaves end - disable ban
|
||||
if (playerByName != null) {
|
||||
return banIp(source, playerByName.getIpAddress(), reason);
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/commands/BanPlayerCommands.java b/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
index ac3ba9d0ea344fa189912d359b718fbe05e7aa49..61a4db144f721b47ac1000df72263bceb6e38ec0 100644
|
||||
--- a/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
+++ b/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
@@ -44,8 +44,16 @@ public class BanPlayerCommands {
|
||||
private static int banPlayers(CommandSourceStack source, Collection<GameProfile> gameProfiles, @Nullable Component reason) throws CommandSyntaxException {
|
||||
UserBanList bans = source.getServer().getPlayerList().getBans();
|
||||
int i = 0;
|
||||
-
|
||||
+ boolean hasBot = false; // Leaves - disable kick
|
||||
for (GameProfile gameProfile : gameProfiles) {
|
||||
+ // Leaves start - disable ban
|
||||
+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ hasBot = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Leaves end - disable ban
|
||||
+ ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
|
||||
if (!bans.isBanned(gameProfile)) {
|
||||
UserBanListEntry userBanListEntry = new UserBanListEntry(
|
||||
gameProfile, null, source.getTextName(), null, reason == null ? null : reason.getString()
|
||||
@@ -55,7 +63,6 @@ public class BanPlayerCommands {
|
||||
source.sendSuccess(
|
||||
() -> Component.translatable("commands.ban.success", Component.literal(gameProfile.getName()), userBanListEntry.getReason()), true
|
||||
);
|
||||
- ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
|
||||
if (player != null) {
|
||||
player.connection.disconnect(Component.translatable("multiplayer.disconnect.banned"), org.bukkit.event.player.PlayerKickEvent.Cause.BANNED); // Paper - kick event cause
|
||||
}
|
||||
@@ -63,7 +70,13 @@ public class BanPlayerCommands {
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
- throw ERROR_ALREADY_BANNED.create();
|
||||
+ // Leaves start - disable kick
|
||||
+ if (hasBot) {
|
||||
+ return i;
|
||||
+ } else {
|
||||
+ throw ERROR_ALREADY_BANNED.create();
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java
|
||||
index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88686b8785 100644
|
||||
--- a/net/minecraft/server/commands/KickCommand.java
|
||||
+++ b/net/minecraft/server/commands/KickCommand.java
|
||||
@@ -46,9 +46,17 @@ public class KickCommand {
|
||||
if (!source.getServer().isPublished()) {
|
||||
throw ERROR_SINGLEPLAYER.create();
|
||||
} else {
|
||||
+ boolean hasBot = false; // Leaves - disable kick
|
||||
int i = 0;
|
||||
|
||||
for (ServerPlayer serverPlayer : players) {
|
||||
+ // Leaves start - disable kick
|
||||
+ if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ hasBot = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
if (!source.getServer().isSingleplayerOwner(serverPlayer.getGameProfile())) {
|
||||
serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause
|
||||
source.sendSuccess(() -> Component.translatable("commands.kick.success", serverPlayer.getDisplayName(), reason), true);
|
||||
@@ -57,7 +65,13 @@ public class KickCommand {
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
- throw ERROR_KICKING_OWNER.create();
|
||||
+ // Leaves start - disable kick
|
||||
+ if (hasBot) {
|
||||
+ return i;
|
||||
+ } else {
|
||||
+ throw ERROR_KICKING_OWNER.create();
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
|
||||
index f2286b96b8f40b4588f817913c42ae7b4a92340f..e6c7bbb023000b9de90c1256274ff5aba4a6478a 100644
|
||||
--- a/net/minecraft/server/commands/OpCommand.java
|
||||
+++ b/net/minecraft/server/commands/OpCommand.java
|
||||
@@ -43,6 +43,7 @@ public class OpCommand {
|
||||
int i = 0;
|
||||
|
||||
for (GameProfile gameProfile : gameProfiles) {
|
||||
+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) continue; // Leaves - disable op
|
||||
if (!playerList.isOp(gameProfile)) {
|
||||
playerList.op(gameProfile);
|
||||
i++;
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f604b0d6890 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
|
||||
}
|
||||
|
||||
// Spigot start
|
||||
+ this.setBotList(new org.leavesmc.leaves.bot.BotList(this)); // Leaves - fakeplayer
|
||||
this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings"));
|
||||
org.spigotmc.SpigotConfig.registerCommands();
|
||||
@@ -173,6 +174,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // Luminol - load config file
|
||||
fun.bm.lophine.utils.ServerI18nUtil.init(); // Lophine - I18n support
|
||||
+ this.getBotList().loadBotInfo(); // Leaves - load resident bot info
|
||||
if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
|
||||
if (this.convertOldUsers()) {
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348fcbaf9ded 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -134,7 +134,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
public final AtomicInteger tickingGenerated = new AtomicInteger(); // Paper - public
|
||||
private final String storageName;
|
||||
//private final PlayerMap playerMap = new PlayerMap(); // Folia - region threading
|
||||
- //public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
|
||||
+ public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
|
||||
private final Long2ByteMap chunkTypeCache = new Long2ByteOpenHashMap();
|
||||
// Paper - rewrite chunk system
|
||||
public int serverViewDistance;
|
||||
@@ -1309,6 +1309,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
} else if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
+ // Leaves start - render bot
|
||||
+ if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
|
||||
+ if (bot.needSendFakeData(player)) {
|
||||
+ bot.sendFakeData(player.connection, false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - render bot
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6cf992049 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
|
||||
private final StructureCheck structureCheck;
|
||||
public final boolean tickTime; // Folia - region threading
|
||||
private final RandomSequences randomSequences;
|
||||
+ final List<ServerPlayer> realPlayers; // Leaves - skip
|
||||
|
||||
// CraftBukkit start
|
||||
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
|
||||
@@ -635,6 +636,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Paper end - rewrite chunk system
|
||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked
|
||||
+ this.realPlayers = Lists.newArrayList(); // Leaves - skip
|
||||
}
|
||||
|
||||
// Folia start - region threading
|
||||
@@ -2389,6 +2391,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
return this.players;
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer skip
|
||||
+ public List<ServerPlayer> realPlayers() {
|
||||
+ return this.realPlayers;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer skip
|
||||
+
|
||||
@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
|
||||
// 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);
|
||||
+ // Leaves start - skip
|
||||
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ ServerLevel.this.realPlayers.add(serverPlayer);
|
||||
+ }
|
||||
+ // Leaves end - skip
|
||||
if (serverPlayer.isReceivingWaypoints()) {
|
||||
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
|
||||
}
|
||||
@@ -2913,6 +2926,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer serverPlayer) {
|
||||
ServerLevel.this.players.remove(serverPlayer);
|
||||
+ // Leaves start - skip
|
||||
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ ServerLevel.this.realPlayers.remove(serverPlayer);
|
||||
+ }
|
||||
+ // Leaves end - skip
|
||||
ServerLevel.this.getWaypointManager().removePlayer(serverPlayer);
|
||||
ServerLevel.this.updateSleepingPlayerList();
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
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
|
||||
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
|
||||
public ServerGamePacketListenerImpl connection;
|
||||
private final MinecraftServer server;
|
||||
- public final ServerPlayerGameMode gameMode;
|
||||
+ public ServerPlayerGameMode gameMode; // Leaves - not final
|
||||
private final PlayerAdvancements advancements;
|
||||
private final ServerStatsCounter stats;
|
||||
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
||||
@@ -232,7 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private int lastSentFood = -99999999;
|
||||
private boolean lastFoodSaturationZero = true;
|
||||
public int lastSentExp = -99999999;
|
||||
- private int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
+ public int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
|
||||
public ParticleStatus particleStatus = ParticleStatus.ALL;
|
||||
private boolean canChatColor = true;
|
||||
@@ -241,7 +241,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private Entity camera;
|
||||
public boolean isChangingDimension;
|
||||
public boolean seenCredits = false;
|
||||
- private final ServerRecipeBook recipeBook;
|
||||
+ protected ServerRecipeBook recipeBook; // Leaves - not final and private -> protected
|
||||
@Nullable
|
||||
private Vec3 levitationStartPos;
|
||||
private int levitationStartTime;
|
||||
@@ -436,6 +436,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
// Paper start - rewrite chunk system
|
||||
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
|
||||
private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
|
||||
+ // Leaves start - player operation limiter
|
||||
+ private int instaBreakCountPerTick = 0;
|
||||
+ private int placeBlockCountPerTick = 0;
|
||||
+ // Leaves end - player operation limiter
|
||||
|
||||
@Override
|
||||
public final boolean moonrise$isRealPlayer() {
|
||||
@@ -924,6 +928,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.tickClientLoadTimeout();
|
||||
+ this.resetOperationCountPerTick(); // Leaves - player operation limiter
|
||||
this.gameMode.tick();
|
||||
this.wardenSpawnTracker.tick();
|
||||
if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
|
||||
@@ -2029,6 +2034,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.lastSentHealth = -1.0F;
|
||||
this.lastSentFood = -1;
|
||||
this.teleportSpectators(teleportTransition, serverLevel);
|
||||
+ // Leaves start - bot support
|
||||
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
|
||||
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
// CraftBukkit start
|
||||
org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld());
|
||||
this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
|
||||
@@ -3577,4 +3587,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity();
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Leaves start - player operation limiter
|
||||
+ protected void resetOperationCountPerTick() {
|
||||
+ instaBreakCountPerTick = 0;
|
||||
+ placeBlockCountPerTick = 0;
|
||||
+ }
|
||||
+
|
||||
+ public int getInstaBreakCountPerTick() {
|
||||
+ return instaBreakCountPerTick;
|
||||
+ }
|
||||
+
|
||||
+ public int getPlaceBlockCountPerTick() {
|
||||
+ return placeBlockCountPerTick;
|
||||
+ }
|
||||
+
|
||||
+ public void addInstaBreakCountPerTick() {
|
||||
+ ++instaBreakCountPerTick;
|
||||
+ }
|
||||
+
|
||||
+ public void addPlaceBlockCountPerTick() {
|
||||
+ ++placeBlockCountPerTick;
|
||||
+ }
|
||||
+
|
||||
+ public boolean allowOperation() {
|
||||
+ return (instaBreakCountPerTick == 0 || placeBlockCountPerTick == 0) && (instaBreakCountPerTick <= 1 && placeBlockCountPerTick <= 2);
|
||||
+ }
|
||||
+ // Leaves end - player operation limiter
|
||||
}
|
||||
diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java
|
||||
index 144a2644c15f276f02bb3be859dc5d05a677ac55..c6a89e8936cffa49b3de153ed3c40e3cc9b8ae61 100644
|
||||
--- a/net/minecraft/server/players/GameProfileCache.java
|
||||
+++ b/net/minecraft/server/players/GameProfileCache.java
|
||||
@@ -125,6 +125,12 @@ public class GameProfileCache {
|
||||
// Paper end
|
||||
|
||||
public Optional<GameProfile> get(String name) {
|
||||
+ // Leaves start - fix bot
|
||||
+ org.leavesmc.leaves.bot.ServerBot bot = org.leavesmc.leaves.bot.BotList.INSTANCE.getBotByName(name);
|
||||
+ if (bot != null) {
|
||||
+ return Optional.of(bot.getGameProfile());
|
||||
+ }
|
||||
+ // Leaves end - fix bot
|
||||
String string = name.toLowerCase(Locale.ROOT);
|
||||
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
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -425,6 +425,19 @@ public abstract class PlayerList {
|
||||
|
||||
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
|
||||
|
||||
+ // Leaves start - bot support
|
||||
+ 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().bots.forEach(bot1 -> {
|
||||
+ bot1.sendPlayerInfo(player);
|
||||
+ bot1.sendFakeDataIfNeed(player, true);
|
||||
+ }); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
+
|
||||
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
|
||||
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
@@ -922,6 +935,12 @@ public abstract class PlayerList {
|
||||
}
|
||||
// Paper end - Add PlayerPostRespawnEvent
|
||||
|
||||
+ // Leaves start - bot support
|
||||
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
|
||||
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(serverPlayer, true)); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
+
|
||||
// CraftBukkit end
|
||||
|
||||
return serverPlayer;
|
||||
@@ -1026,11 +1045,16 @@ public abstract class PlayerList {
|
||||
|
||||
public String[] getPlayerNamesArray() {
|
||||
List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
|
||||
- String[] strings = new String[this.players.size()];
|
||||
+ String[] strings = new String[this.players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
|
||||
|
||||
for (int i = 0; i < players.size(); i++) { // Folia - region threading
|
||||
strings[i] = players.get(i).getGameProfile().getName(); // Folia - region threading
|
||||
}
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ for (int i = this.players.size(); i < strings.length; ++i) {
|
||||
+ strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().getName();
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer support
|
||||
|
||||
return strings;
|
||||
}
|
||||
@@ -1141,7 +1165,14 @@ public abstract class PlayerList {
|
||||
|
||||
@Nullable
|
||||
public ServerPlayer getPlayerByName(String username) {
|
||||
- return this.playersByName.get(username.toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ username = username.toLowerCase(java.util.Locale.ROOT);
|
||||
+ ServerPlayer player = this.playersByName.get(username);
|
||||
+ if (player == null) {
|
||||
+ player = this.server.getBotList().getBotByName(username);
|
||||
+ }
|
||||
+ return player; // Spigot
|
||||
+ // Leaves end - fakeplayer support
|
||||
}
|
||||
|
||||
public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey<Level> dimension, Packet<?> packet) {
|
||||
@@ -1482,7 +1513,13 @@ public abstract class PlayerList {
|
||||
|
||||
@Nullable
|
||||
public ServerPlayer getPlayer(UUID playerUUID) {
|
||||
- return this.playersByUUID.get(playerUUID);
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ ServerPlayer player = this.playersByUUID.get(playerUUID);
|
||||
+ if (player == null) {
|
||||
+ player = this.server.getBotList().getBot(playerUUID);
|
||||
+ }
|
||||
+ return player;
|
||||
+ // Leaves start - fakeplayer support
|
||||
}
|
||||
|
||||
public boolean canBypassPlayerLimit(GameProfile profile) {
|
||||
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd13444f4ad 100644
|
||||
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||
@@ -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
|
||||
this.waypoints.add(waypoint);
|
||||
|
||||
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
|
||||
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 47ef63061737f3efdb0ce7ec71a8d9c920385bb0..674c4cc7443545f7e333d2bcec9e5fc98000ecae 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
|
||||
|
||||
BlockPos onPosLegacy = this.getOnPosLegacy();
|
||||
BlockState blockState = this.level().getBlockState(onPosLegacy);
|
||||
- if (this.isLocalInstanceAuthoritative()) {
|
||||
+ if (this.isLocalInstanceAuthoritative() || this instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves - ServerBot needs check fall damage
|
||||
this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy);
|
||||
}
|
||||
|
||||
@@ -1539,7 +1539,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
// Paper start - optimise collisions
|
||||
- private Vec3 collide(Vec3 movement) {
|
||||
+ public Vec3 collide(Vec3 movement) { // Leaves - private -> public
|
||||
final boolean xZero = movement.x == 0.0;
|
||||
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 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
|
||||
private void travelRidden(Player player, Vec3 travelVector) {
|
||||
Vec3 riddenInput = this.getRiddenInput(player, travelVector);
|
||||
this.tickRidden(player, riddenInput);
|
||||
- if (this.canSimulateMovement()) {
|
||||
+ if (this.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves - Fakeplayer
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(riddenInput);
|
||||
} else {
|
||||
@@ -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));
|
||||
- if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !usingItem.useOnRelease()) {
|
||||
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide && !usingItem.useOnRelease()) { // Leaves - Fakeplayer skip this check
|
||||
this.useItemRemaining = 0;
|
||||
// Paper end - lag compensate eating
|
||||
this.completeUsingItem();
|
||||
@@ -4239,6 +4239,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
this.stopUsingItem();
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ public boolean releaseUsingItemWithResult() {
|
||||
+ ItemStack itemInHand = this.getItemInHand(this.getUsedItemHand());
|
||||
+ boolean result = false;
|
||||
+ if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemInHand, this.useItem)) {
|
||||
+ this.useItem = itemInHand;
|
||||
+ result = this.useItem.releaseUsingWithResult(this.level(), this, this.getUseItemRemainingTicks());
|
||||
+ if (this.useItem.useOnRelease()) {
|
||||
+ this.updatingUsingItem();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.stopUsingItem();
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
public void stopUsingItem() {
|
||||
if (!this.level().isClientSide) {
|
||||
boolean isUsingItem = this.isUsingItem();
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 6c933c27ce155eb516a9ede96fb2c3bd19251bfa..6e0784af90aab5c25100613f97d4492fa7d1b277 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -205,7 +205,7 @@ public abstract class Player extends LivingEntity {
|
||||
private int lastLevelUpTime;
|
||||
public GameProfile gameProfile;
|
||||
private boolean reducedDebugInfo;
|
||||
- private ItemStack lastItemInMainHand = ItemStack.EMPTY;
|
||||
+ protected ItemStack lastItemInMainHand = ItemStack.EMPTY;
|
||||
private final ItemCooldowns cooldowns = this.createItemCooldowns();
|
||||
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
|
||||
@Nullable
|
||||
@@ -412,6 +412,12 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer
|
||||
+ protected void livingEntityTick() {
|
||||
+ super.tick();
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
@Override
|
||||
protected float getMaxHeadRotationRelativeToBody() {
|
||||
return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody();
|
||||
@@ -714,7 +720,7 @@ public abstract class Player extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
- private void touch(Entity entity) {
|
||||
+ public void touch(Entity entity) { // Leaves - private -> public
|
||||
entity.playerTouch(this);
|
||||
}
|
||||
|
||||
@@ -1339,7 +1345,7 @@ public abstract class Player extends LivingEntity {
|
||||
this.sweepAttack();
|
||||
}
|
||||
|
||||
- if (target instanceof ServerPlayer && target.hurtMarked) {
|
||||
+ if ((target instanceof ServerPlayer && !(target instanceof org.leavesmc.leaves.bot.ServerBot)) && target.hurtMarked) { // Leaves - bot knockback
|
||||
// CraftBukkit start - Add Velocity Event
|
||||
boolean cancelled = false;
|
||||
org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity();
|
||||
diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 7760ab1fe365b4bf1ab6c2ff953e8659a28008a8..76f6b0932633bc5670a1cdc76ff78b3bc725401d 100644
|
||||
--- a/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -58,7 +58,7 @@ public class FishingHook extends Projectile {
|
||||
public static final EntityDataAccessor<Integer> DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Boolean> DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN);
|
||||
private int life;
|
||||
- private int nibble;
|
||||
+ public int nibble; // Leaves - private -> public
|
||||
public int timeUntilLured;
|
||||
public int timeUntilHooked;
|
||||
public float fishAngle;
|
||||
diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
index 91ac54fb0ae9a06945476cbd1caa20be32c4a9fe..be380db0cb2f243b4a3cf8bd1b06d38debc5f6fd 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java
|
||||
@@ -271,6 +271,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+ } else if (this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves start - Fakeplayer
|
||||
+ this.floatBoat();
|
||||
+ this.controlBoat();
|
||||
+ this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+ // Leaves end - Fakeplayer
|
||||
} else {
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
}
|
||||
@@ -383,6 +388,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ @Override
|
||||
+ public boolean canSimulateMovement() {
|
||||
+ return super.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
@Nullable
|
||||
protected SoundEvent getPaddleSound() {
|
||||
return switch (this.getStatus()) {
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index bdc0ca1f625dc264bef6e5722ec66121ba48625a..525610be29d5077a3199287347b1b71cf9fd8abf 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -407,6 +407,7 @@ public abstract class AbstractContainerMenu {
|
||||
|
||||
private void doClick(int slotId, int button, ClickType clickType, Player player) {
|
||||
Inventory inventory = player.getInventory();
|
||||
+ if (!doClickCheck(slotId, button, clickType, player)) return; // Leaves - doClick check
|
||||
if (clickType == ClickType.QUICK_CRAFT) {
|
||||
int i = this.quickcraftStatus;
|
||||
this.quickcraftStatus = getQuickcraftHeader(button);
|
||||
@@ -685,6 +686,22 @@ public abstract class AbstractContainerMenu {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - doClick check
|
||||
+ private boolean doClickCheck(int slotIndex, int button, ClickType actionType, Player player) {
|
||||
+ if (slotIndex < 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ Slot slot = getSlot(slotIndex);
|
||||
+ ItemStack itemStack = slot.getItem();
|
||||
+ net.minecraft.world.item.component.CustomData customData = itemStack.get(net.minecraft.core.component.DataComponents.CUSTOM_DATA);
|
||||
+ if (customData != null && customData.contains("Leaves.Gui.Placeholder")) {
|
||||
+ return !customData.copyTag().getBoolean("Leaves.Gui.Placeholder").orElse(false);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Leaves end - doClick check
|
||||
+
|
||||
private boolean tryItemClickBehaviourOverride(Player player, ClickAction action, Slot slot, ItemStack clickedItem, ItemStack carriedItem) {
|
||||
FeatureFlagSet featureFlagSet = player.level().enabledFeatures();
|
||||
return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player)
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index a27e1d53abc2d8b8912226add33510067e10ed52..be0a267e5564a30c16f408cb311a448f354d60b4 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -450,7 +450,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(serverLevel, player, hand, blocks.getFirst(), clickedPos);
|
||||
}
|
||||
|
||||
- if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
|
||||
+ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild()) && (!(player instanceof org.leavesmc.leaves.bot.ServerBot))) { // Leaves - Fakeplayer skip this check
|
||||
interactionResult = InteractionResult.FAIL; // cancel placement
|
||||
// PAIL: Remove this when MC-99075 fixed
|
||||
player.containerMenu.forceHeldSlot(hand);
|
||||
@@ -946,6 +946,20 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ public boolean releaseUsingWithResult(Level level, LivingEntity livingEntity, int timeLeft) {
|
||||
+ ItemStack itemStack = this.copy();
|
||||
+ if (this.getItem().releaseUsing(this, level, livingEntity, timeLeft)) {
|
||||
+ ItemStack itemStack1 = this.applyAfterUseComponentSideEffects(livingEntity, itemStack);
|
||||
+ if (itemStack1 != this) {
|
||||
+ livingEntity.setItemInHand(livingEntity.getUsedItemHand(), itemStack1);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
public boolean useOnRelease() {
|
||||
return this.getItem().useOnRelease(this);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
index bff9574bece5f5581d9cc51a3f2b68b5c13c25c9..4bfe53c15c9b2effd24dddc48565efc9c102e56a 100644
|
||||
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
@@ -145,7 +145,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!(entity instanceof ServerPlayer)) {
|
||||
+ if (!(entity instanceof ServerPlayer) || (entity instanceof org.leavesmc.leaves.bot.ServerBot)) { // Leaves - bot slime block
|
||||
Vec3 deltaMovement = entity.getDeltaMovement();
|
||||
double d1 = deltaMovement.x;
|
||||
double d2 = deltaMovement.y;
|
||||
diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
index ecfd6a04ea1bac75bbb7e88554b73fc67e7f7358..2c9a55eecf44eaa62ef57597a94d657ad0b9cfc4 100644
|
||||
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -49,6 +49,11 @@ public class PhantomSpawner implements CustomSpawner {
|
||||
ServerStatsCounter stats = serverPlayer.getStats();
|
||||
int i = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
|
||||
int i1 = 24000;
|
||||
+ // Leaves start - fakeplayer spawn
|
||||
+ if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot bot && bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.SPAWN_PHANTOM)) {
|
||||
+ i1 = Math.max(bot.notSleepTicks, 1);
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer spawn
|
||||
if (randomSource.nextInt(i) >= 72000) {
|
||||
BlockPos blockPos1 = blockPos.above(20 + randomSource.nextInt(15))
|
||||
.east(-10 + randomSource.nextInt(21))
|
||||
diff --git a/net/minecraft/world/level/storage/LevelResource.java b/net/minecraft/world/level/storage/LevelResource.java
|
||||
index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b53f6d9a6d 100644
|
||||
--- a/net/minecraft/world/level/storage/LevelResource.java
|
||||
+++ b/net/minecraft/world/level/storage/LevelResource.java
|
||||
@@ -15,7 +15,7 @@ public class LevelResource {
|
||||
public static final LevelResource ROOT = new LevelResource(".");
|
||||
private final String id;
|
||||
|
||||
- private LevelResource(String id) {
|
||||
+ public LevelResource(String id) { // Leaves - private -> public
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
index fe44d8d17d2622b3d6021c11579af85ef96737bb..0aae211dc2048f8cd14213c2a868394d1ed16070 100644
|
||||
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
@@ -19,7 +19,7 @@ import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public class PlayerDataStorage {
|
||||
+public class PlayerDataStorage implements org.leavesmc.leaves.bot.IPlayerDataStorage {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final File playerDir;
|
||||
protected final DataFixer fixerUpper;
|
||||
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
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 8e5b79db12882432de575f2a76aa36eac6fc8f51..977a4ac391b8cf8b59c5c77becf9a5951d513526 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -346,9 +346,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: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
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 4882df428369e87bcf23b532dd970b13b3adfb88..e51f99de547f09f98b9e351bf84d8411994b62bc 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -757,6 +757,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
|
||||
public void setLoaded(final boolean loaded) {
|
||||
this.loaded = loaded;
|
||||
+ // Leaves start - bbor
|
||||
+ if (loaded) {
|
||||
+ org.leavesmc.leaves.protocol.BBORProtocol.onChunkLoaded(this);
|
||||
+ }
|
||||
+ // Leaves end - bbor
|
||||
}
|
||||
|
||||
public Level getLevel() {
|
||||
@@ -1,20 +0,0 @@
|
||||
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,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
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 168702a5ae51a2bc42c5761e13cb14008a8162c4..ebd2f2887780d9c6c3c44983bac23eab732cf43f 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1105,6 +1105,7 @@ public abstract class PlayerList {
|
||||
//player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level))); // Paper - rewrite chunk system
|
||||
//player.connection.send(new ClientboundSetSimulationDistancePacket(io.papermc.paper.FeatureHooks.getSimulationDistance(level))); // Paper - rewrite chunk system
|
||||
// Paper end - view distances
|
||||
+ 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: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
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 33f9870a4f966a887023b1debd4ab9ef9d24378f..89983e7da244434a5346b23b49c748349cd79e34 100644
|
||||
--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
+++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
@@ -115,6 +115,12 @@ public class SmithingTransformRecipe extends SimpleSmithingRecipe {
|
||||
);
|
||||
}
|
||||
|
||||
+ // Leaves start - REI
|
||||
+ public SlotDisplay getResult() {
|
||||
+ return new SlotDisplay.ItemStackSlotDisplay(this.result);
|
||||
+ }
|
||||
+ // 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 f9fa7d0eaf9f32959a4bd12b82e5a49ea808a44c..2f3241563ad7e5ed5663b913671d2af056df97bb 100644
|
||||
--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
|
||||
+++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
|
||||
@@ -109,6 +109,12 @@ public class SmithingTrimRecipe extends SimpleSmithingRecipe {
|
||||
return Optional.of(this.addition);
|
||||
}
|
||||
|
||||
+ // Leaves start
|
||||
+ public Holder<TrimPattern> pattern() {
|
||||
+ return pattern;
|
||||
+ }
|
||||
+ // Leaves end
|
||||
+
|
||||
@Override
|
||||
public RecipeSerializer<SmithingTrimRecipe> getSerializer() {
|
||||
return SERIALIZER;
|
||||
@@ -0,0 +1,127 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Fri, 13 Feb 2026 16:17:36 +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/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 977a4ac391b8cf8b59c5c77becf9a5951d513526..bc38b16dd296cca9bc5556b95117794e633a9c27 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3902,7 +3902,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
@Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add PlayerLoadedWorldEvent
|
||||
- private void markClientLoaded() {
|
||||
+ public void markClientLoaded() { // Lophine - private -> public
|
||||
// Paper start - Add PlayerLoadedWorldEvent
|
||||
this.markClientLoaded(false);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
index 03ec05a860781f85e58055d6f58893963781bd97..c15f0a3d419fea50d4349fa864e83bf7fee78b9f 100644
|
||||
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
|
||||
@@ -72,7 +72,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(final EntityType<? extends Animal> type, final Level level) {
|
||||
diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
index 3d4bfeae2fddb9ace26e7dea8870704d8309862b..d2862d2e6f599265bc319000bba05609e0bea2c3 100644
|
||||
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
@@ -255,7 +255,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 f08a25b76e689c2242e8ef8226c3d8c2dcec1c70..6e76e472bd1e7242f6cd7986c23ebc38d16fd46a 100644
|
||||
--- a/net/minecraft/world/level/storage/loot/LootPool.java
|
||||
+++ b/net/minecraft/world/level/storage/loot/LootPool.java
|
||||
@@ -36,7 +36,7 @@ public class LootPool implements Validatable {
|
||||
)
|
||||
.apply(i, 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 14fc07badbd14a5a4c8e8c7d237d08a4eb6a6f12..0aaf2240a0f79b5c4aaa9c22dca7b2f0953dac49 100644
|
||||
--- a/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
+++ b/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
@@ -49,7 +49,7 @@ public class LootTable implements Validatable {
|
||||
public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of());
|
||||
private final ContextKeySet paramSet;
|
||||
private final Optional<Identifier> 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 53e4375a4af610e54309f2978e59985e6ada15f5..615b533caecef09d967c615ae39ef29c80784575 100644
|
||||
--- a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
|
||||
+++ b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
|
||||
@@ -17,7 +17,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(final List<LootPoolEntryContainer> children, final 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 83c514c213251dd5470627d0299b5858b850784d..d231f706388e6967d2e29f806a9f52e8f7f5ba61 100644
|
||||
--- a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
|
||||
+++ b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
|
||||
@@ -15,7 +15,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, Validatable {
|
||||
- protected final List<LootItemCondition> conditions;
|
||||
+ public final List<LootItemCondition> conditions; // Leaves - private -> public
|
||||
private final Predicate<LootContext> compositeCondition;
|
||||
|
||||
protected LootPoolEntryContainer(final 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 20520b7071f19af2882a797ee40019cddd76e378..11c4333ab28cffcfb97bcd289930b33c4baae993 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(
|
||||
final Either<ResourceKey<LootTable>, LootTable> contents,
|
||||
diff --git a/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java b/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
|
||||
index cb821605781050282fd0a28e3d096fa18de833b8..99624ca2e895884a5e92a965af2064803c0d3b14 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.Validatable;
|
||||
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(final List<LootItemCondition> terms, final Predicate<LootContext> composedPredicate) {
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 3 Feb 2025 13:51:26 +0800
|
||||
Subject: [PATCH] Leaves: Alternative block placement 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: MIT
|
||||
|
||||
This patch is Powered by
|
||||
carpet-extra(https://github.com/gnembon/carpet-extra)
|
||||
MasaGadget(https://github.com/plusls/MasaGadget)
|
||||
litematica(https://github.com/maruohon/litematica)
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index bc38b16dd296cca9bc5556b95117794e633a9c27..57aff87cc7be0cb7136689412490cd399eff15eb 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2183,7 +2183,7 @@ public class ServerGamePacketListenerImpl
|
||||
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.level(), pos.getX() >> 4, pos.getZ() >> 4, 8) && this.player.isWithinBlockInteractionRange(pos, 1.0)) { // Folia - do not allow players to interact with blocks outside the current region
|
||||
Vec3 distance = location.subtract(Vec3.atCenterOf(pos));
|
||||
double limit = 1.0000001;
|
||||
- if (Math.abs(distance.x()) < 1.0000001 && Math.abs(distance.y()) < 1.0000001 && Math.abs(distance.z()) < 1.0000001) {
|
||||
+ if (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.needIgnoreDistance() ||Math.abs(distance.x()) < 1.0000001 && Math.abs(distance.y()) < 1.0000001 && Math.abs(distance.z()) < 1.0000001) { // Leaves - disableDistanceCheckForUseItem
|
||||
Direction direction = blockHit.getDirection();
|
||||
this.player.resetLastActionTime();
|
||||
int maxY = level.getMaxY();
|
||||
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||
index 3167be4b7c2c61ef725af4a832d759ab6e061af0..2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f 100644
|
||||
--- a/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/net/minecraft/world/item/BlockItem.java
|
||||
@@ -136,7 +136,7 @@ public class BlockItem extends Item {
|
||||
}
|
||||
|
||||
protected @Nullable BlockState getPlacementState(final BlockPlaceContext context) {
|
||||
- BlockState stateForPlacement = this.getBlock().getStateForPlacement(context);
|
||||
+ BlockState stateForPlacement = this.getBlock().getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||
return stateForPlacement != null && this.canPlace(context, stateForPlacement) ? stateForPlacement : null;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
index d5d499226d0b2c2adfae7bbb4c28c96c80411c44..cb0a4a9865df69e5504a86de6c144bc4450bd19a 100644
|
||||
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
@@ -26,14 +26,14 @@ public class StandingAndWallBlockItem extends BlockItem {
|
||||
|
||||
@Override
|
||||
protected @Nullable BlockState getPlacementState(final BlockPlaceContext context) {
|
||||
- BlockState wallState = this.wallBlock.getStateForPlacement(context);
|
||||
+ BlockState wallState = this.wallBlock.getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||
BlockState stateForPlacement = null;
|
||||
LevelReader level = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
|
||||
for (Direction direction : context.getNearestLookingDirections()) {
|
||||
if (direction != this.attachmentDirection.getOpposite()) {
|
||||
- BlockState possibleState = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : wallState;
|
||||
+ BlockState possibleState = direction == this.attachmentDirection ? this.getBlock().getRealStateForPlacement(context) : wallState; // Leaves - alternativeBlockPlacement
|
||||
if (possibleState != null && this.canPlace(level, possibleState, pos)) {
|
||||
stateForPlacement = possibleState;
|
||||
break;
|
||||
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
|
||||
index 0cdd88e530c660b65f3eb331b37cbd2c69fc2ff5..62dec122c5e23150dc107d3fab5a552f86d34565 100644
|
||||
--- a/net/minecraft/world/level/block/Block.java
|
||||
+++ b/net/minecraft/world/level/block/Block.java
|
||||
@@ -516,6 +516,32 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
public void stepOn(final Level level, final BlockPos pos, final BlockState onState, final Entity entity) {
|
||||
}
|
||||
|
||||
+ // Leaves start - alternativeBlockPlacement
|
||||
+ public @Nullable BlockState getRealStateForPlacement(final BlockPlaceContext context) {
|
||||
+ BlockState vanillaState = this.getStateForPlacement(context);
|
||||
+ switch (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.alternativeBlockPlacement) {
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET -> {
|
||||
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacement(this, context);
|
||||
+ if (tryState != null) {
|
||||
+ return tryState;
|
||||
+ }
|
||||
+ }
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET_FIX -> {
|
||||
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacementFix(this, context);
|
||||
+ if (tryState != null) {
|
||||
+ return tryState;
|
||||
+ }
|
||||
+ }
|
||||
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.LITEMATICA -> {
|
||||
+ if (vanillaState != null) {
|
||||
+ return org.leavesmc.leaves.protocol.LitematicaEasyPlaceProtocol.applyPlacementProtocol(vanillaState, context);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return vanillaState;
|
||||
+ }
|
||||
+ // Leaves end - alternativeBlockPlacement
|
||||
+
|
||||
public @Nullable BlockState getStateForPlacement(final BlockPlaceContext context) {
|
||||
return this.defaultBlockState();
|
||||
}
|
||||
@@ -0,0 +1,775 @@
|
||||
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: Fakeplayer
|
||||
|
||||
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/advancements/criterion/SimpleCriterionTrigger.java b/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
|
||||
index dfce5ced082de0caaff8da071fb632cd6ae787c9..d5c1862ebf6066859da74f47fa0be0256ba0f653 100644
|
||||
--- a/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
|
||||
+++ b/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
|
||||
@@ -41,6 +41,7 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
|
||||
}
|
||||
|
||||
protected void trigger(final ServerPlayer player, final Predicate<T> matcher) {
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) return; // Leaves - bot skip
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
Set<CriterionTrigger.Listener<T>> allListeners = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
|
||||
if (allListeners != null && !allListeners.isEmpty()) {
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index efbbc1a40d203a2818eeda2a4e938b9a6117f1c3..6b85a5ad9af0c57a0d4d5b55f62b82c5ff69b0e8 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -74,7 +74,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
public boolean preparing = true;
|
||||
// Spigot end
|
||||
private volatile @Nullable PacketListener disconnectListener;
|
||||
- private volatile @Nullable PacketListener packetListener;
|
||||
+ protected volatile @Nullable PacketListener packetListener; // Leaves - private -> protected
|
||||
private @Nullable DisconnectionDetails disconnectionDetails;
|
||||
private boolean encrypted;
|
||||
private final java.util.concurrent.atomic.AtomicBoolean disconnectionHandled = new java.util.concurrent.atomic.AtomicBoolean(false); // Folia - region threading - may be called concurrently during configuration stage
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 0bedaa20bc2cae75a48357e69740ada2380a03dd..86393793dd1b90f033c93c70933e1e4a7546eb15 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -297,6 +297,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Paper - per-level scheduledEvents
|
||||
private final ServerClockManager clockManager;
|
||||
|
||||
+ private org.leavesmc.leaves.bot.BotList botList; // Leaves - fakeplayer
|
||||
+
|
||||
public static <S extends MinecraftServer> S spin(final Function<Thread, S> factory) {
|
||||
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
||||
AtomicReference<S> serverReference = new AtomicReference<>();
|
||||
@@ -1120,6 +1122,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
LOGGER.info("Stopping server");
|
||||
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
|
||||
+ this.getBotList().removeAll(); // Leaves - save or remove bot
|
||||
// CraftBukkit start
|
||||
if (this.server != null) {
|
||||
if (false) this.server.spark.disable(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
@@ -1695,7 +1698,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
int emptyTickThreshold = this.pauseWhenEmptySeconds() * 20;
|
||||
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
|
||||
if (false && emptyTickThreshold > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
|
||||
- if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping
|
||||
+ if (this.playerList.getPlayerCount() == 0 && this.botList.bots.isEmpty() && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping // Leaves - fakeplayer
|
||||
this.emptyTicks++;
|
||||
} else {
|
||||
this.emptyTicks = 0;
|
||||
@@ -1827,6 +1830,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.isSaving = true;
|
||||
if (playerSaveInterval > 0) {
|
||||
this.playerList.saveAll(playerSaveInterval);
|
||||
+ org.leavesmc.leaves.bot.BotList.INSTANCE.saveAllResumeBots(playerSaveInterval); // Leaves - resident fakeplayer
|
||||
}
|
||||
if (region == null && fullSave) { // Folia - region threading - don't auto save level data
|
||||
this.saveGlobalData(false);
|
||||
@@ -2065,6 +2069,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
protected void tickConnection() {
|
||||
this.getConnection().tick();
|
||||
+ this.botList.networkTick(); // Leaves - fakeplayer
|
||||
}
|
||||
|
||||
public void forceGameTimeSynchronization() {
|
||||
@@ -3270,6 +3275,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.debugSubscribers;
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer
|
||||
+ protected void setBotList(org.leavesmc.leaves.bot.BotList botList) {
|
||||
+ this.botList = botList;
|
||||
+ }
|
||||
+
|
||||
+ public org.leavesmc.leaves.bot.BotList getBotList() {
|
||||
+ return botList;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
public record ReloadableResources(CloseableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable {
|
||||
@Override
|
||||
public void close() {
|
||||
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
||||
index 658db8460122db271bbc3c2c0844574b8d75f044..89448eee9f135de8b406bf5f4147b3298e33ba17 100644
|
||||
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -168,6 +168,11 @@ public class PlayerAdvancements {
|
||||
}
|
||||
|
||||
public boolean award(final AdvancementHolder holder, final String criterion) {
|
||||
+ // Leaves start - bot can't get advancement
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Leaves end - bot can't get advancement
|
||||
boolean result = false;
|
||||
AdvancementProgress progress = this.getOrStartProgress(holder);
|
||||
boolean wasDone = progress.isDone();
|
||||
diff --git a/net/minecraft/server/commands/BanIpCommands.java b/net/minecraft/server/commands/BanIpCommands.java
|
||||
index 36b858bfe123edc2f1c5c7861dd0e4475ef7a5f1..e52a2ad8408d9691701dc51fa702efdb51f0acbb 100644
|
||||
--- a/net/minecraft/server/commands/BanIpCommands.java
|
||||
+++ b/net/minecraft/server/commands/BanIpCommands.java
|
||||
@@ -40,6 +40,12 @@ public class BanIpCommands {
|
||||
return banIp(source, target, reason);
|
||||
} else {
|
||||
ServerPlayer player = source.getServer().getPlayerList().getPlayerByName(target);
|
||||
+ // Leaves start - disable ban
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ return 0;
|
||||
+ }
|
||||
+ // Leaves end - disable ban
|
||||
if (player != null) {
|
||||
return banIp(source, player.getIpAddress(), reason);
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/commands/BanPlayerCommands.java b/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
index c87bc86c57fde9d92e3927bdead5cdaf2e935744..950f8ed955bc09713348936ae7aa1a8b14006c2a 100644
|
||||
--- a/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
+++ b/net/minecraft/server/commands/BanPlayerCommands.java
|
||||
@@ -38,8 +38,15 @@ public class BanPlayerCommands {
|
||||
private static int banPlayers(final CommandSourceStack source, final Collection<NameAndId> players, final @Nullable Component reason) throws CommandSyntaxException {
|
||||
UserBanList list = source.getServer().getPlayerList().getBans();
|
||||
int count = 0;
|
||||
-
|
||||
+ boolean hasBot = false; // Leaves - disable kick
|
||||
for (NameAndId player : players) {
|
||||
+ // Leaves start - disable ban
|
||||
+ if (player.isBot()) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ hasBot = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Leaves end - disable ban
|
||||
if (!list.isBanned(player)) {
|
||||
UserBanListEntry entry = new UserBanListEntry(player, null, source.getTextName(), null, reason == null ? null : reason.getString());
|
||||
list.add(entry);
|
||||
@@ -53,7 +60,13 @@ public class BanPlayerCommands {
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
- throw ERROR_ALREADY_BANNED.create();
|
||||
+ // Leaves start - disable kick
|
||||
+ if (hasBot) {
|
||||
+ return count;
|
||||
+ } else {
|
||||
+ throw ERROR_ALREADY_BANNED.create();
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java
|
||||
index 0227dd63f67537d769494e122616873c18d35350..18d49018b1330cfcaa91d9b02d0d23e4ba941809 100644
|
||||
--- a/net/minecraft/server/commands/KickCommand.java
|
||||
+++ b/net/minecraft/server/commands/KickCommand.java
|
||||
@@ -38,9 +38,17 @@ public class KickCommand {
|
||||
if (!source.getServer().isPublished()) {
|
||||
throw ERROR_SINGLEPLAYER.create();
|
||||
} else {
|
||||
+ boolean hasBot = false; // Leaves - disable kick
|
||||
int count = 0;
|
||||
|
||||
for (ServerPlayer player : players) {
|
||||
+ // Leaves start - disable kick
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ source.sendFailure(Component.literal("Permission denied"));
|
||||
+ hasBot = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
if (!source.getServer().isSingleplayerOwner(player.nameAndId())) {
|
||||
player.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause
|
||||
source.sendSuccess(() -> Component.translatable("commands.kick.success", player.getDisplayName(), reason), true);
|
||||
@@ -49,7 +57,13 @@ public class KickCommand {
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
- throw ERROR_KICKING_OWNER.create();
|
||||
+ // Leaves start - disable kick
|
||||
+ if (hasBot) {
|
||||
+ return count;
|
||||
+ } else {
|
||||
+ throw ERROR_KICKING_OWNER.create();
|
||||
+ }
|
||||
+ // Leaves end - disable kick
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
|
||||
index 636f56bfc0e9075b257e2eb14e858975bdedd801..20cbc0e65fea3fc2d0033259c2f35e158ea81926 100644
|
||||
--- a/net/minecraft/server/commands/OpCommand.java
|
||||
+++ b/net/minecraft/server/commands/OpCommand.java
|
||||
@@ -39,6 +39,7 @@ public class OpCommand {
|
||||
int count = 0;
|
||||
|
||||
for (NameAndId player : players) {
|
||||
+ if (player.isBot()) continue; // Leaves - disable op
|
||||
if (!list.isOp(player)) {
|
||||
list.op(player);
|
||||
count++;
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 1bc1e9a77dca7acfe5f989f6439f185d0d2e20a6..1790e8c141a8d3f7ccf4b11f9a28b3582325e317 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -274,6 +274,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
|
||||
// Spigot start
|
||||
+ this.setBotList(new org.leavesmc.leaves.bot.BotList(this)); // Leaves - fakeplayer
|
||||
this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
|
||||
org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings"));
|
||||
org.spigotmc.SpigotConfig.registerCommands();
|
||||
@@ -295,6 +296,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
consoleThread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
|
||||
if (false) this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
|
||||
+ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info
|
||||
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
|
||||
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 0dfb25ad032429a2aea7aa441dd5fd1848a6c617..215f2a40921cc8e6b181c0a34aa1bbaf843e3059 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1388,6 +1388,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
}
|
||||
} else {
|
||||
this.removePlayer(player);
|
||||
+ // Leaves start - render bot
|
||||
+ if (this.entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
|
||||
+ if (bot.needSendFakeData(player)) {
|
||||
+ bot.sendFakeData(player.connection, false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - render bot
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 049339ae33569d627d2a00ef6cab9cad02c4c014..e05705884a285143b8a3ebad00cb489efe47d532 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -240,6 +240,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
//public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent // Folia - region threading - move to regionised world data
|
||||
//public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent // Folia - region threading - move to regionised world data
|
||||
//private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) // Folia - region threading - move to regionised world data
|
||||
+ final List<ServerPlayer> realPlayers; // Leaves - skip
|
||||
|
||||
@Override
|
||||
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
@@ -706,6 +707,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler);
|
||||
// Paper end - rewrite chunk system
|
||||
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
|
||||
+ this.realPlayers = Lists.newArrayList(); // Leaves - skip
|
||||
this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked
|
||||
}
|
||||
|
||||
@@ -2611,6 +2613,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
return this.players;
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer skip
|
||||
+ public List<ServerPlayer> realPlayers() {
|
||||
+ return this.realPlayers;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer skip
|
||||
+
|
||||
@Override
|
||||
public void updatePOIOnBlockStateChange(final BlockPos pos, final BlockState oldState, final BlockState newState) {
|
||||
Optional<Holder<PoiType>> oldType = PoiTypes.forState(oldState);
|
||||
@@ -3091,6 +3099,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// 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 player) {
|
||||
ServerLevel.this.players.add(player);
|
||||
+ // Leaves start - skip
|
||||
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ ServerLevel.this.realPlayers.add(player);
|
||||
+ }
|
||||
+ // Leaves end - skip
|
||||
if (player.isReceivingWaypoints()) {
|
||||
ServerLevel.this.getWaypointManager().addPlayer(player);
|
||||
}
|
||||
@@ -3172,6 +3185,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
ServerLevel.this.players.remove(player);
|
||||
+ // Leaves start - skip
|
||||
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ ServerLevel.this.realPlayers.remove(player);
|
||||
+ }
|
||||
+ // Leaves end - skip
|
||||
ServerLevel.this.getWaypointManager().removePlayer(player);
|
||||
ServerLevel.this.updateSleepingPlayerList();
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index f3afab1100a35cc9ab091944de93d1f30ef040a7..7f6d4118ede7e02fdea8961fd736d00ce41c64bb 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -23,6 +23,8 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
+
|
||||
+import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.CrashReportCategory;
|
||||
@@ -229,7 +231,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
|
||||
public ServerGamePacketListenerImpl connection;
|
||||
private final MinecraftServer server;
|
||||
- public final ServerPlayerGameMode gameMode;
|
||||
+ public ServerPlayerGameMode gameMode; // Leaves - not final
|
||||
private final PlayerAdvancements advancements;
|
||||
private final ServerStatsCounter stats;
|
||||
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
||||
@@ -250,7 +252,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private @Nullable Entity camera;
|
||||
public boolean isChangingDimension;
|
||||
public boolean seenCredits = false;
|
||||
- private final ServerRecipeBook recipeBook;
|
||||
+ protected ServerRecipeBook recipeBook; // Leaves - not final and private -> protected
|
||||
private @Nullable Vec3 levitationStartPos;
|
||||
private int levitationStartTime;
|
||||
private boolean disconnected;
|
||||
@@ -1514,7 +1516,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
// Luminol End - Cross Region Damage trace
|
||||
|
||||
- private void tellNeutralMobsThatIDied() {
|
||||
+ protected void tellNeutralMobsThatIDied() { // Leaves private -> protected
|
||||
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
|
||||
this.level()
|
||||
.getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS)
|
||||
@@ -2180,6 +2182,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.lastSentHealth = -1.0F;
|
||||
this.lastSentFood = -1;
|
||||
this.teleportSpectators(transition, oldLevel);
|
||||
+ // Leaves start - bot support
|
||||
+ if (FakeplayerConfig.enable) {
|
||||
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
// CraftBukkit start
|
||||
org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), oldLevel.getWorld());
|
||||
this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
|
||||
diff --git a/net/minecraft/server/players/CachedUserNameToIdResolver.java b/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
index 50c64f4be138f08e8a57fb10888dbfbc364c91af..382fc20df48d7d554833715a9c9f62ea7464a25d 100644
|
||||
--- a/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
+++ b/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
@@ -122,6 +122,12 @@ public class CachedUserNameToIdResolver implements UserNameToIdResolver {
|
||||
|
||||
@Override
|
||||
public Optional<NameAndId> get(final String name) {
|
||||
+ // Leaves start - fix bot
|
||||
+ org.leavesmc.leaves.bot.ServerBot bot = org.leavesmc.leaves.bot.BotList.INSTANCE.getBotByName(name);
|
||||
+ if (bot != null) {
|
||||
+ return Optional.of(bot.nameAndId());
|
||||
+ }
|
||||
+ // Leaves end - fix bot
|
||||
String userName = name.toLowerCase(Locale.ROOT);
|
||||
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||
CachedUserNameToIdResolver.GameProfileInfo profileInfo = this.profilesByName.get(userName);
|
||||
diff --git a/net/minecraft/server/players/NameAndId.java b/net/minecraft/server/players/NameAndId.java
|
||||
index 484714beb5f7cdf8178834c5edd4f847fb06ebb8..ba7a280aad07f36366c15cd158b36ca9768cef19 100644
|
||||
--- a/net/minecraft/server/players/NameAndId.java
|
||||
+++ b/net/minecraft/server/players/NameAndId.java
|
||||
@@ -8,18 +8,22 @@ import java.util.UUID;
|
||||
import net.minecraft.core.UUIDUtil;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
-public record NameAndId(UUID id, String name) {
|
||||
+public record NameAndId(UUID id, String name, boolean isBot) { // Leaves - fakeplayer
|
||||
public static final Codec<NameAndId> CODEC = RecordCodecBuilder.create(
|
||||
i -> i.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name))
|
||||
.apply(i, NameAndId::new)
|
||||
);
|
||||
|
||||
public NameAndId(final GameProfile profile) {
|
||||
- this(profile.id(), profile.name());
|
||||
+ this(profile.id(), profile.name(), com.google.common.collect.Iterables.getFirst(profile.properties().get("is_bot"), "false").equals("true")); // Leaves - fakeplayer
|
||||
}
|
||||
|
||||
public NameAndId(final com.mojang.authlib.yggdrasil.response.NameAndId profile) {
|
||||
- this(profile.id(), profile.name());
|
||||
+ this(profile.id(), profile.name(), false); // Leaves - fakeplayer
|
||||
+ }
|
||||
+
|
||||
+ public NameAndId(UUID uuid, String name) {
|
||||
+ this(uuid, name, false); // Leaves - fakeplayer
|
||||
}
|
||||
|
||||
public static @Nullable NameAndId fromJson(final JsonObject object) {
|
||||
@@ -33,7 +37,7 @@ public record NameAndId(UUID id, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
- return new NameAndId(uuid, object.get("name").getAsString());
|
||||
+ return new NameAndId(uuid, object.get("name").getAsString(), false); // Leaves - fakeplayer
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -46,7 +50,7 @@ public record NameAndId(UUID id, String name) {
|
||||
|
||||
public static NameAndId createOffline(final String name) {
|
||||
UUID id = UUIDUtil.createOfflinePlayerUUID(name);
|
||||
- return new NameAndId(id, name);
|
||||
+ return new NameAndId(id, name, false); // Leaves - fakeplayer
|
||||
}
|
||||
|
||||
// Paper start - utility method for common conversion back to the game profile
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index ebd2f2887780d9c6c3c44983bac23eab732cf43f..4edc952087c3255ca488b140402621bbf6495770 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -22,6 +22,8 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
+
|
||||
+import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -319,6 +321,19 @@ public abstract class PlayerList {
|
||||
|
||||
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
||||
|
||||
+ // Leaves start - bot support
|
||||
+ if (FakeplayerConfig.enable) {
|
||||
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
|
||||
+ if (bot != null) {
|
||||
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
|
||||
+ }
|
||||
+ this.server.getBotList().bots.forEach(bot1 -> {
|
||||
+ bot1.sendPlayerInfo(player);
|
||||
+ bot1.sendFakeDataIfNeed(player, true);
|
||||
+ }); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
+
|
||||
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
||||
|
||||
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
|
||||
@@ -791,6 +806,11 @@ public abstract class PlayerList {
|
||||
respawnReason
|
||||
).callEvent();
|
||||
// Paper end
|
||||
+ // Leaves start - bot support
|
||||
+ if (FakeplayerConfig.enable) {
|
||||
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
|
||||
return player;
|
||||
}
|
||||
@@ -893,11 +913,16 @@ public abstract class PlayerList {
|
||||
|
||||
public String[] getPlayerNamesArray() {
|
||||
List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
|
||||
- String[] names = new String[players.size()]; // Folia - region threading
|
||||
+ String[] names = new String[players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
|
||||
|
||||
for (int i = 0; i < players.size(); i++) { // Folia - region threading
|
||||
names[i] = players.get(i).getGameProfile().name(); // Folia - region threading
|
||||
}
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ for (int i = this.players.size(); i < names.length; ++i) {
|
||||
+ names[i] = this.server.getBotList().bots.get(i - this.players.size()).gameProfile.name();
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer support
|
||||
|
||||
return names;
|
||||
}
|
||||
@@ -1016,8 +1041,15 @@ public abstract class PlayerList {
|
||||
|| this.allowCommandsForAllPlayers;
|
||||
}
|
||||
|
||||
- public @Nullable ServerPlayer getPlayerByName(final String name) {
|
||||
- return this.playersByName.get(name.toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
+ public @Nullable ServerPlayer getPlayerByName(String name) {
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ name = name.toLowerCase(java.util.Locale.ROOT);
|
||||
+ ServerPlayer player = this.playersByName.get(name);
|
||||
+ if (player == null) {
|
||||
+ player = this.server.getBotList().getBotByName(name);
|
||||
+ }
|
||||
+ return player; // Spigot
|
||||
+ // Leaves end - fakeplayer support
|
||||
}
|
||||
|
||||
public void broadcast(
|
||||
@@ -1360,7 +1392,13 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public @Nullable ServerPlayer getPlayer(final UUID uuid) {
|
||||
- return this.playersByUUID.get(uuid);
|
||||
+ // Leaves start - fakeplayer support
|
||||
+ ServerPlayer player = this.playersByUUID.get(uuid);
|
||||
+ if (player == null) {
|
||||
+ player = this.server.getBotList().getBot(uuid);
|
||||
+ }
|
||||
+ return player;
|
||||
+ // Leaves start - fakeplayer support
|
||||
}
|
||||
|
||||
public @Nullable ServerPlayer getPlayer(final String playerName) {
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index b69698f47ccb0f1ac3eeea05a02ab9d798319b44..b073a91fd67d092713c53db6f3df75c655dc8fcd 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1257,7 +1257,7 @@ public abstract class Entity
|
||||
|
||||
BlockPos effectPos = this.getOnPosLegacy();
|
||||
BlockState effectState = this.level().getBlockState(effectPos);
|
||||
- if (this.isLocalInstanceAuthoritative()) {
|
||||
+ if (this.isLocalInstanceAuthoritative() || this instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves - ServerBot needs check fall damage
|
||||
this.checkFallDamage(movement.y, this.onGround(), effectState, effectPos);
|
||||
}
|
||||
|
||||
@@ -1593,7 +1593,7 @@ public abstract class Entity
|
||||
return colliders.isEmpty() ? maxDistance : -Shapes.collide(Direction.Axis.Y, aabb, colliders, -maxDistance);
|
||||
}
|
||||
|
||||
- private Vec3 collide(final Vec3 movement) {
|
||||
+ public Vec3 collide(final Vec3 movement) { // Leaves - private -> public
|
||||
// Paper start - optimise collisions
|
||||
final boolean xZero = movement.x == 0.0;
|
||||
final boolean yZero = movement.y == 0.0;
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 1e820f34636f415ef78cdfbed06c6952a3cf1c0b..8a8de7f4d62532709805ebde531dc71ad78fa5c9 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3347,7 +3347,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
private void travelRidden(final Player controller, final Vec3 selfInput) {
|
||||
Vec3 riddenInput = this.getRiddenInput(controller, selfInput);
|
||||
this.tickRidden(controller, riddenInput);
|
||||
- if (this.canSimulateMovement()) {
|
||||
+ if (this.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves - Fakeplayer
|
||||
this.setSpeed(this.getRiddenSpeed(controller));
|
||||
this.travel(riddenInput);
|
||||
} else {
|
||||
@@ -4270,7 +4270,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));
|
||||
- if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide() && !useItem.useOnRelease()) {
|
||||
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide() && !useItem.useOnRelease()) {
|
||||
this.useItemRemaining = 0;
|
||||
// Paper end - lag compensate eating
|
||||
this.completeUsingItem();
|
||||
@@ -4459,6 +4459,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
this.stopUsingItem();
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ public boolean releaseUsingItemWithResult() {
|
||||
+ ItemStack itemInHand = this.getItemInHand(this.getUsedItemHand());
|
||||
+ boolean result = false;
|
||||
+ if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemInHand, this.useItem)) {
|
||||
+ this.useItem = itemInHand;
|
||||
+ result = this.useItem.releaseUsingWithResult(this.level(), this, this.getUseItemRemainingTicks());
|
||||
+ if (this.useItem.useOnRelease()) {
|
||||
+ this.updatingUsingItem();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.stopUsingItem();
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
public void stopUsingItem() {
|
||||
if (!this.level().isClientSide()) {
|
||||
boolean wasUsingItem = this.isUsingItem();
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index f6f6d21f3393a3ab79a84212b0d66d83d0e817f1..38689fa466a20c64f9916ee32a57a9fdb58d9403 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -167,7 +167,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
private int lastLevelUpTime;
|
||||
public GameProfile gameProfile;
|
||||
private boolean reducedDebugInfo;
|
||||
- private ItemStack lastItemInMainHand = ItemStack.EMPTY;
|
||||
+ protected ItemStack lastItemInMainHand = ItemStack.EMPTY; // Leaves - fakeplayer
|
||||
private final ItemCooldowns cooldowns = this.createItemCooldowns();
|
||||
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
|
||||
public @Nullable FishingHook fishing;
|
||||
@@ -340,6 +340,12 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
this.updatePlayerPose();
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer
|
||||
+ protected void livingEntityTick() {
|
||||
+ super.tick();
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
@Override
|
||||
protected float getMaxHeadRotationRelativeToBody() {
|
||||
return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody();
|
||||
@@ -565,7 +571,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
public void removeEntitiesOnShoulder() {
|
||||
}
|
||||
|
||||
- private void touch(final Entity entity) {
|
||||
+ public void touch(final Entity entity) { // Leaves - private -> public
|
||||
entity.playerTouch(this);
|
||||
}
|
||||
|
||||
@@ -1247,7 +1253,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
// Paper end - Configurable sprint interruption on attack
|
||||
}
|
||||
|
||||
- if (entity instanceof ServerPlayer && entity.hurtMarked) {
|
||||
+ if ((entity instanceof ServerPlayer && !(entity instanceof org.leavesmc.leaves.bot.ServerBot)) && entity.hurtMarked) { // Leaves - bot knockback
|
||||
// CraftBukkit start - Add Velocity Event
|
||||
boolean cancelled = false;
|
||||
org.bukkit.entity.Player player = (org.bukkit.entity.Player) entity.getBukkitEntity();
|
||||
diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 0c8a48988c859669cf7e38816aaf32782c245244..a554e050d0c582c441af9d5616367234caa67ab0 100644
|
||||
--- a/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -58,7 +58,7 @@ public class FishingHook extends Projectile {
|
||||
public static final EntityDataAccessor<Integer> DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Boolean> DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN);
|
||||
private int life;
|
||||
- private int nibble;
|
||||
+ public int nibble; // Leaves - private -> public
|
||||
public int timeUntilLured;
|
||||
public int timeUntilHooked;
|
||||
public float fishAngle;
|
||||
diff --git a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
index 05176458264b110ef3280342866ace22ec5a3333..2ce33513fd8e3de912c69ca8bc558a5800784ac5 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
@@ -270,6 +270,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+ } else if (this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves start - Fakeplayer
|
||||
+ this.floatBoat();
|
||||
+ this.controlBoat();
|
||||
+ this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
+ // Leaves end - Fakeplayer
|
||||
} else {
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
}
|
||||
@@ -380,6 +385,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ @Override
|
||||
+ public boolean canSimulateMovement() {
|
||||
+ return super.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
protected @Nullable SoundEvent getPaddleSound() {
|
||||
return switch (this.getStatus()) {
|
||||
case IN_WATER, UNDER_WATER, UNDER_FLOWING_WATER -> SoundEvents.BOAT_PADDLE_WATER;
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index fa1f7dd22959632aaa54e72c8caf13ea072e7ca7..ae6056c3b6ae3eebdfb59cf54d7333dfc2cebf6a 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -407,6 +407,7 @@ public abstract class AbstractContainerMenu {
|
||||
|
||||
private void doClick(final int slotIndex, final int buttonNum, final ContainerInput containerInput, final Player player) {
|
||||
Inventory inventory = player.getInventory();
|
||||
+ if (!doClickCheck(slotIndex, buttonNum, containerInput, player)) return; // Leaves - doClick check
|
||||
if (containerInput == ContainerInput.QUICK_CRAFT) {
|
||||
int expectedStatus = this.quickcraftStatus;
|
||||
this.quickcraftStatus = getQuickcraftHeader(buttonNum);
|
||||
@@ -681,6 +682,22 @@ public abstract class AbstractContainerMenu {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - doClick check
|
||||
+ private boolean doClickCheck(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) {
|
||||
+ if (slotIndex < 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ Slot slot = getSlot(slotIndex);
|
||||
+ ItemStack itemStack = slot.getItem();
|
||||
+ net.minecraft.world.item.component.CustomData customData = itemStack.get(net.minecraft.core.component.DataComponents.CUSTOM_DATA);
|
||||
+ if (customData != null && customData.contains("Leaves.Gui.Placeholder")) {
|
||||
+ return !customData.copyTag().getBoolean("Leaves.Gui.Placeholder").orElse(false);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Leaves end - doClick check
|
||||
+
|
||||
private boolean tryItemClickBehaviourOverride(
|
||||
final Player player, final ClickAction clickAction, final Slot slot, final ItemStack clicked, final ItemStack carried
|
||||
) {
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index dd4a92a0ea94d16669535bde9b6728515dafe7f4..77f3bf9d9c0bb08a151adf1abd22e22d0fc83bf3 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -453,7 +453,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(level, player, hand, blocks.getFirst(), pos);
|
||||
}
|
||||
|
||||
- if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
|
||||
+ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild()) && (!(player instanceof org.leavesmc.leaves.bot.ServerBot))) { // Leaves - Fakeplayer skip this check
|
||||
result = InteractionResult.FAIL; // cancel placement
|
||||
// PAIL: Remove this when MC-99075 fixed
|
||||
player.containerMenu.forceHeldSlot(hand);
|
||||
@@ -982,6 +982,20 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - Fakeplayer
|
||||
+ public boolean releaseUsingWithResult(Level level, LivingEntity livingEntity, int timeLeft) {
|
||||
+ ItemStack itemStack = this.copy();
|
||||
+ if (this.getItem().releaseUsing(this, level, livingEntity, timeLeft)) {
|
||||
+ ItemStack itemStack1 = this.applyAfterUseComponentSideEffects(livingEntity, itemStack);
|
||||
+ if (itemStack1 != this) {
|
||||
+ livingEntity.setItemInHand(livingEntity.getUsedItemHand(), itemStack1);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Leaves end - Fakeplayer
|
||||
+
|
||||
public boolean useOnRelease() {
|
||||
return this.getItem().useOnRelease(this);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
index 282849162b88354893a15533e66d046fdd035bd6..2ecb10fe97d15954e44c61247eabc8818eb16f34 100644
|
||||
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
@@ -152,7 +152,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!(entity instanceof ServerPlayer)) {
|
||||
+ if (!(entity instanceof ServerPlayer) || (entity instanceof org.leavesmc.leaves.bot.ServerBot)) { // Leaves - bot slime block
|
||||
Vec3 deltaMovement = entity.getDeltaMovement();
|
||||
double dx = deltaMovement.x;
|
||||
double dy = deltaMovement.y;
|
||||
diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
index 9d7238a28440ddc442c9288a617795261df767d9..142ab133d3b68eb9b88651e307653f1aafdf1de3 100644
|
||||
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -49,6 +49,10 @@ public class PhantomSpawner implements CustomSpawner {
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
int value = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
|
||||
int dayLength = 24000;
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot bot && bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.SPAWN_PHANTOM)) {
|
||||
+ dayLength = Math.max(bot.notSleepTicks, 1);
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer spawn
|
||||
if (random.nextInt(value) >= level.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper - Ability to control player's insomnia and phantoms
|
||||
BlockPos spawnPos = playerPos.above(20 + random.nextInt(15))
|
||||
.east(-10 + random.nextInt(21))
|
||||
@@ -0,0 +1,560 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 15:48:12 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves) & ReplayMod (https://github.com/ReplayMod)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
This patch is Powered by ReplayMod (https://github.com/ReplayMod)
|
||||
|
||||
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
|
||||
index 28776f3363810259f8c3bfdfd9f8c0455975be2a..0f562d7403aebf6c0907f2a33f758f4351ef282e 100644
|
||||
--- a/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -562,7 +562,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, ExecutionCo
|
||||
|
||||
@Override
|
||||
public Collection<String> getOnlinePlayerNames() {
|
||||
- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
|
||||
+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
index 7e3912b8b29e40eb3347f1451b0fd3ebee2af4f1..0834e402e6af7028e08851378e15390ec6314380 100644
|
||||
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||
@@ -142,11 +142,12 @@ public class EntitySelector {
|
||||
return this.findPlayers(sender);
|
||||
} else if (this.playerName != null) {
|
||||
ServerPlayer result = sender.getServer().getPlayerList().getPlayerByName(this.playerName);
|
||||
+ result = result instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : result; // Leaves - skip photographer
|
||||
return result == null ? List.of() : List.of(result);
|
||||
} else if (this.entityUUID != null) {
|
||||
for (ServerLevel level : sender.getServer().getAllLevels()) {
|
||||
Entity entity = level.getEntity(this.entityUUID);
|
||||
- if (entity != null) {
|
||||
+ if (entity != null && !(entity instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
|
||||
if (entity.getType().isEnabled(sender.enabledFeatures())) {
|
||||
return List.of(entity);
|
||||
}
|
||||
@@ -160,7 +161,7 @@ public class EntitySelector {
|
||||
AABB absoluteAabb = this.getAbsoluteAabb(pos);
|
||||
if (this.currentEntity) {
|
||||
Predicate<Entity> predicate = this.getPredicate(pos, absoluteAabb, null);
|
||||
- return sender.getEntity() != null && predicate.test(sender.getEntity()) ? List.of(sender.getEntity()) : List.of();
|
||||
+ return sender.getEntity() != null && !(sender.getEntity() instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(sender.getEntity()) ? List.of(sender.getEntity()) : List.of(); // Leaves - skip photographer
|
||||
} else {
|
||||
Predicate<Entity> predicate = this.getPredicate(pos, absoluteAabb, sender.enabledFeatures());
|
||||
List<Entity> result = new ObjectArrayList<>();
|
||||
@@ -171,6 +172,7 @@ public class EntitySelector {
|
||||
this.addEntities(result, levelx, absoluteAabb, predicate);
|
||||
}
|
||||
}
|
||||
+ result.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
|
||||
|
||||
return this.sortAndLimit(pos, result);
|
||||
}
|
||||
@@ -206,9 +208,11 @@ public class EntitySelector {
|
||||
this.checkPermissions(sender);
|
||||
if (this.playerName != null) {
|
||||
ServerPlayer result = sender.getServer().getPlayerList().getPlayerByName(this.playerName);
|
||||
+ result = result instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : result; // Leaves - skip photographer
|
||||
return result == null ? List.of() : List.of(result);
|
||||
} else if (this.entityUUID != null) {
|
||||
ServerPlayer result = sender.getServer().getPlayerList().getPlayer(this.entityUUID);
|
||||
+ result = result instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : result; // Leaves - skip photographer
|
||||
return result == null ? List.of() : List.of(result);
|
||||
} else {
|
||||
Vec3 pos = this.position.apply(sender.getPosition());
|
||||
@@ -220,11 +224,11 @@ public class EntitySelector {
|
||||
int limit = this.getResultLimit();
|
||||
List<ServerPlayer> result;
|
||||
if (this.isWorldLimited()) {
|
||||
- result = sender.getLevel().getPlayers(predicate, limit);
|
||||
+ result = sender.getLevel().getPlayers((player -> !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(player)), limit); // Leaves - skip photographer
|
||||
} else {
|
||||
result = new ObjectArrayList<>();
|
||||
|
||||
- for (ServerPlayer player : sender.getServer().getPlayerList().getPlayers()) {
|
||||
+ for (ServerPlayer player : sender.getServer().getPlayerList().realPlayers) { // Leaves - only real players
|
||||
if (predicate.test(player)) {
|
||||
result.add(player);
|
||||
if (result.size() >= limit) {
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 86393793dd1b90f033c93c70933e1e4a7546eb15..48f7d57f6d3ef4250e6b3cf42055d29d94d3f6e3 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1921,7 +1921,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
private ServerStatus.Players buildPlayerStatus() {
|
||||
- List<ServerPlayer> players = new java.util.ArrayList<>(this.playerList.getPlayers()); // Folia - region threading
|
||||
+ List<ServerPlayer> players = new java.util.ArrayList<>(this.playerList.realPlayers); // Folia - region threading // Leaves - only real player
|
||||
int maxPlayers = this.getMaxPlayers();
|
||||
if (this.hidesOnlinePlayers()) {
|
||||
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||
@@ -2142,7 +2142,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
- return this.playerList.getPlayerCount();
|
||||
+ return this.playerList.realPlayers.size(); // Leaves - only real player
|
||||
}
|
||||
|
||||
public String[] getPlayerNames() {
|
||||
@@ -2354,7 +2354,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
} else {
|
||||
int count = 0;
|
||||
|
||||
- for (ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||
+ for (ServerPlayer player : this.getPlayerList().realPlayers) { // Leaves - only real player
|
||||
player.getBukkitEntity().taskScheduler.schedule((ServerPlayer updatedPlayer) -> { // Folia - region threading
|
||||
// Paper start - Expand PlayerGameModeChangeEvent
|
||||
org.bukkit.event.player.PlayerGameModeChangeEvent event = updatedPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null); // Folia - region threading
|
||||
@@ -2541,7 +2541,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||
// Paper start - we don't need to save everything, just advancements
|
||||
// this.getPlayerList().saveAll();
|
||||
- for (final ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||
+ for (final ServerPlayer player : this.getPlayerList().realPlayers) { // Leaves - only real players
|
||||
player.getAdvancements().save();
|
||||
}
|
||||
// Paper end - we don't need to save everything, just advancements
|
||||
@@ -2677,7 +2677,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
PlayerList playerList = this.getPlayerList();
|
||||
UserWhiteList whiteList = playerList.getWhiteList();
|
||||
|
||||
- for (ServerPlayer player : Lists.newArrayList(playerList.getPlayers())) {
|
||||
+ for (ServerPlayer player : Lists.newArrayList(playerList.realPlayers)) { // Leaves - only real player
|
||||
if (!whiteList.isWhiteListed(player.nameAndId()) && !this.getPlayerList().isOp(player.nameAndId())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420)
|
||||
player.connection.disconnect(net.kyori.adventure.text.Component.text(org.spigotmc.SpigotConfig.whitelistMessage), org.bukkit.event.player.PlayerKickEvent.Cause.WHITELIST); // Paper - use configurable message & kick event cause
|
||||
}
|
||||
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
||||
index 89448eee9f135de8b406bf5f4147b3298e33ba17..b286aefc7d328bc7a7f44ce93615392075d9fef7 100644
|
||||
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -169,7 +169,7 @@ public class PlayerAdvancements {
|
||||
|
||||
public boolean award(final AdvancementHolder holder, final String criterion) {
|
||||
// Leaves start - bot can't get advancement
|
||||
- if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot || player instanceof org.leavesmc.leaves.replay.ServerPhotographer) { // Leaves - and photographer
|
||||
return false;
|
||||
}
|
||||
// Leaves end - bot can't get advancement
|
||||
diff --git a/net/minecraft/server/ServerScoreboard.java b/net/minecraft/server/ServerScoreboard.java
|
||||
index 9bf09b888425e491072864265c8de3885154a0ba..97a8fee8280061312a28013a5400e835db2eb474 100644
|
||||
--- a/net/minecraft/server/ServerScoreboard.java
|
||||
+++ b/net/minecraft/server/ServerScoreboard.java
|
||||
@@ -245,7 +245,7 @@ public class ServerScoreboard extends Scoreboard {
|
||||
public void startTrackingObjective(final Objective objective) {
|
||||
List<Packet<?>> packets = this.getStartTrackingPackets(objective);
|
||||
|
||||
- for (ServerPlayer player : this.server.getPlayerList().getPlayers()) {
|
||||
+ for (ServerPlayer player : this.server.getPlayerList().realPlayers) { // Leaves - only real players
|
||||
if (player.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||
for (Packet<?> packet : packets) {
|
||||
player.connection.send(packet);
|
||||
@@ -271,7 +271,7 @@ public class ServerScoreboard extends Scoreboard {
|
||||
public void stopTrackingObjective(final Objective objective) {
|
||||
List<Packet<?>> packets = this.getStopTrackingPackets(objective);
|
||||
|
||||
- for (ServerPlayer player : this.server.getPlayerList().getPlayers()) {
|
||||
+ for (ServerPlayer player : this.server.getPlayerList().realPlayers) { // Leaves - only real players
|
||||
if (player.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||
for (Packet<?> packet : packets) {
|
||||
player.connection.send(packet);
|
||||
diff --git a/net/minecraft/server/commands/ListPlayersCommand.java b/net/minecraft/server/commands/ListPlayersCommand.java
|
||||
index b850c908a594f839ce124c6bd01762d31cc3aa1e..b2240fd3f5ace03168fd679932675a72c09e81d7 100644
|
||||
--- a/net/minecraft/server/commands/ListPlayersCommand.java
|
||||
+++ b/net/minecraft/server/commands/ListPlayersCommand.java
|
||||
@@ -33,7 +33,7 @@ public class ListPlayersCommand {
|
||||
private static int format(final CommandSourceStack source, final Function<ServerPlayer, Component> formatter) {
|
||||
PlayerList playerList = source.getServer().getPlayerList();
|
||||
// CraftBukkit start
|
||||
- List<ServerPlayer> playersTemp = playerList.getPlayers();
|
||||
+ List<ServerPlayer> playersTemp = playerList.realPlayers;
|
||||
if (source.getBukkitSender() instanceof org.bukkit.entity.Player) {
|
||||
org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender();
|
||||
playersTemp = playersTemp.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList());
|
||||
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
|
||||
index 20cbc0e65fea3fc2d0033259c2f35e158ea81926..6bcd09b8d39333bd5f2c0d7c0a9a91bb52f9314d 100644
|
||||
--- a/net/minecraft/server/commands/OpCommand.java
|
||||
+++ b/net/minecraft/server/commands/OpCommand.java
|
||||
@@ -25,7 +25,8 @@ public class OpCommand {
|
||||
(c, p) -> {
|
||||
PlayerList list = c.getSource().getServer().getPlayerList();
|
||||
return SharedSuggestionProvider.suggest(
|
||||
- list.getPlayers().stream().filter(player -> !list.isOp(player.nameAndId())).map(pl -> pl.getGameProfile().name()), p
|
||||
+ list.realPlayers // Leaves - only real player
|
||||
+ .stream().filter(player -> !list.isOp(player.nameAndId())).map(pl -> pl.getGameProfile().name()), p
|
||||
);
|
||||
}
|
||||
)
|
||||
diff --git a/net/minecraft/server/commands/ParticleCommand.java b/net/minecraft/server/commands/ParticleCommand.java
|
||||
index a14f82a1587e175030d4cd806726456831008dea..563d897a70f402d556cabd3e02131aaf22ff8d1e 100644
|
||||
--- a/net/minecraft/server/commands/ParticleCommand.java
|
||||
+++ b/net/minecraft/server/commands/ParticleCommand.java
|
||||
@@ -36,7 +36,7 @@ public class ParticleCommand {
|
||||
0.0F,
|
||||
0,
|
||||
false,
|
||||
- c.getSource().getServer().getPlayerList().getPlayers()
|
||||
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||
)
|
||||
)
|
||||
.then(
|
||||
@@ -50,7 +50,7 @@ public class ParticleCommand {
|
||||
0.0F,
|
||||
0,
|
||||
false,
|
||||
- c.getSource().getServer().getPlayerList().getPlayers()
|
||||
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||
)
|
||||
)
|
||||
.then(
|
||||
@@ -68,7 +68,7 @@ public class ParticleCommand {
|
||||
FloatArgumentType.getFloat(c, "speed"),
|
||||
IntegerArgumentType.getInteger(c, "count"),
|
||||
false,
|
||||
- c.getSource().getServer().getPlayerList().getPlayers()
|
||||
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||
)
|
||||
)
|
||||
.then(
|
||||
@@ -82,7 +82,7 @@ public class ParticleCommand {
|
||||
FloatArgumentType.getFloat(c, "speed"),
|
||||
IntegerArgumentType.getInteger(c, "count"),
|
||||
true,
|
||||
- c.getSource().getServer().getPlayerList().getPlayers()
|
||||
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||
)
|
||||
)
|
||||
.then(
|
||||
@@ -112,7 +112,7 @@ public class ParticleCommand {
|
||||
FloatArgumentType.getFloat(c, "speed"),
|
||||
IntegerArgumentType.getInteger(c, "count"),
|
||||
false,
|
||||
- c.getSource().getServer().getPlayerList().getPlayers()
|
||||
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||
)
|
||||
)
|
||||
.then(
|
||||
diff --git a/net/minecraft/server/commands/TeamMsgCommand.java b/net/minecraft/server/commands/TeamMsgCommand.java
|
||||
index d04fd8ab5f8e3c1697af5448c320838a822dbf1f..f46abe413e9b30f219fa1f7fc485de4c8859be90 100644
|
||||
--- a/net/minecraft/server/commands/TeamMsgCommand.java
|
||||
+++ b/net/minecraft/server/commands/TeamMsgCommand.java
|
||||
@@ -40,7 +40,7 @@ public class TeamMsgCommand {
|
||||
} else {
|
||||
List<ServerPlayer> receivers = source.getServer()
|
||||
.getPlayerList()
|
||||
- .getPlayers()
|
||||
+ .realPlayers // Leaves - only real players
|
||||
.stream()
|
||||
.filter(receiver -> receiver == entity || receiver.getTeam() == team)
|
||||
.toList();
|
||||
diff --git a/net/minecraft/server/commands/WhitelistCommand.java b/net/minecraft/server/commands/WhitelistCommand.java
|
||||
index 907d1304503a80c6d0fd064bf1aaf4e081e9f85b..e0c1ee55888261bca42bbadec8812da2a36dded8 100644
|
||||
--- a/net/minecraft/server/commands/WhitelistCommand.java
|
||||
+++ b/net/minecraft/server/commands/WhitelistCommand.java
|
||||
@@ -44,7 +44,7 @@ public class WhitelistCommand {
|
||||
(c, p) -> {
|
||||
PlayerList list = c.getSource().getServer().getPlayerList();
|
||||
return SharedSuggestionProvider.suggest(
|
||||
- list.getPlayers()
|
||||
+ list.realPlayers // Leaves - only real player
|
||||
.stream()
|
||||
.map(Player::nameAndId)
|
||||
.filter(nameAndId -> !list.getWhiteList().isWhiteListed(nameAndId))
|
||||
diff --git a/net/minecraft/server/gui/PlayerListComponent.java b/net/minecraft/server/gui/PlayerListComponent.java
|
||||
index 37c9f983ae89c497f44a1b7967d741abf909e0a0..d7fb2505f2a86ca0d81f144624ef2e1a4b4bddbb 100644
|
||||
--- a/net/minecraft/server/gui/PlayerListComponent.java
|
||||
+++ b/net/minecraft/server/gui/PlayerListComponent.java
|
||||
@@ -17,8 +17,8 @@ public class PlayerListComponent extends JList<String> {
|
||||
if (this.tickCount++ % 20 == 0) {
|
||||
Vector<String> players = new Vector<>();
|
||||
|
||||
- for (int i = 0; i < this.server.getPlayerList().getPlayers().size(); i++) {
|
||||
- players.add(this.server.getPlayerList().getPlayers().get(i).getGameProfile().name());
|
||||
+ for (int i = 0; i < this.server.getPlayerList().realPlayers.size(); i++) { // Leaves - only real players
|
||||
+ players.add(this.server.getPlayerList().realPlayers.get(i).getGameProfile().name()); // Leaves - only real players
|
||||
}
|
||||
|
||||
this.setListData(players);
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index e05705884a285143b8a3ebad00cb489efe47d532..c51b0075cd650085cd991bc89396f605cb520442 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -3100,7 +3100,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
ServerLevel.this.players.add(player);
|
||||
// Leaves start - skip
|
||||
- if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot) && !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
|
||||
ServerLevel.this.realPlayers.add(player);
|
||||
}
|
||||
// Leaves end - skip
|
||||
@@ -3186,7 +3186,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
ServerLevel.this.players.remove(player);
|
||||
// Leaves start - skip
|
||||
- if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot) && !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
|
||||
ServerLevel.this.realPlayers.remove(player);
|
||||
}
|
||||
// Leaves end - skip
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 4edc952087c3255ca488b140402621bbf6495770..a39480a7cd19074daf93accb1f9e7c41e33e775c 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -132,6 +132,7 @@ public abstract class PlayerList {
|
||||
private int simulationDistance;
|
||||
private boolean allowCommandsForAllPlayers;
|
||||
private int sendAllPlayerInfoIn;
|
||||
+ public final List<ServerPlayer> realPlayers = new java.util.concurrent.CopyOnWriteArrayList<>(); // Leaves - replay api
|
||||
|
||||
// CraftBukkit start
|
||||
private org.bukkit.craftbukkit.CraftServer cserver;
|
||||
@@ -193,6 +194,7 @@ public abstract class PlayerList {
|
||||
|
||||
private boolean countConnection(Connection conn, int limit) {
|
||||
synchronized (this.connectionsStateLock) {
|
||||
+ if (conn instanceof org.leavesmc.leaves.bot.ServerBotPacketListenerImpl.BotConnection) return true;
|
||||
int count = this.usersCountedAgainstLimit.size();
|
||||
if (count >= limit) {
|
||||
return false;
|
||||
@@ -223,6 +225,124 @@ public abstract class PlayerList {
|
||||
|
||||
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
|
||||
|
||||
+ // Leaves start - replay mod api
|
||||
+ public void placeNewPhotographer(Connection connection, org.leavesmc.leaves.replay.ServerPhotographer player, ServerLevel worldserver) {
|
||||
+ player.isRealPlayer = true; // Paper
|
||||
+ player.loginTime = System.currentTimeMillis(); // Paper
|
||||
+
|
||||
+ ServerLevel worldserver1 = worldserver;
|
||||
+
|
||||
+ player.setServerLevel(worldserver1);
|
||||
+ player.spawnIn(worldserver1);
|
||||
+ player.gameMode.setLevel(player.level());
|
||||
+
|
||||
+ LevelData worlddata = worldserver1.getLevelData();
|
||||
+
|
||||
+ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, CommonListenerCookie.createInitial(player.gameProfile, false));
|
||||
+ GameRules gamerules = worldserver1.getGameRules();
|
||||
+ boolean flag = gamerules.get(GameRules.IMMEDIATE_RESPAWN);
|
||||
+ boolean flag1 = gamerules.get(GameRules.REDUCED_DEBUG_INFO);
|
||||
+ boolean flag2 = gamerules.get(GameRules.LIMITED_CRAFTING);
|
||||
+
|
||||
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), io.papermc.paper.FeatureHooks.getViewDistance(worldserver1), io.papermc.paper.FeatureHooks.getSimulationDistance(worldserver1), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1), this.server.enforceSecureProfile()));
|
||||
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
|
||||
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
||||
+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
+ RecipeManager craftingmanager = this.server.getRecipeManager();
|
||||
+ playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes()));
|
||||
+
|
||||
+ this.sendPlayerPermissionLevel(player);
|
||||
+ player.getStats().markAllDirty();
|
||||
+ player.getRecipeBook().sendInitialRecipeBook(player);
|
||||
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
|
||||
+ this.server.invalidateStatus();
|
||||
+
|
||||
+ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||
+ ServerStatus serverping = this.server.getStatus();
|
||||
+
|
||||
+ if (serverping != null) {
|
||||
+ player.sendServerStatus(serverping);
|
||||
+ }
|
||||
+
|
||||
+ this.players.add(player);
|
||||
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||
+ this.playersByUUID.put(player.getUUID(), player);
|
||||
+
|
||||
+ player.suppressTrackerForLogin = true;
|
||||
+ worldserver1.addNewPlayer(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||
+
|
||||
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
|
||||
+ if (!player.connection.isAcceptingMessages()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
||||
+
|
||||
+ // Leaves start - bot support
|
||||
+ if (FakeplayerConfig.enable) {
|
||||
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
|
||||
+ if (bot != null) {
|
||||
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
|
||||
+ }
|
||||
+ this.server.getBotList().bots.forEach(bot1 -> {
|
||||
+ bot1.sendPlayerInfo(player);
|
||||
+ bot1.sendFakeDataIfNeed(player, true);
|
||||
+ }); // Leaves - render bot
|
||||
+ }
|
||||
+ // Leaves end - bot support
|
||||
+
|
||||
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
|
||||
+ for (int i = 0; i < this.players.size(); ++i) {
|
||||
+ ServerPlayer entityplayer1 = this.players.get(i);
|
||||
+
|
||||
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // Leaves start - skip photographer
|
||||
+ if (entityplayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Leaves end - skip photographer
|
||||
+
|
||||
+ onlinePlayers.add(entityplayer1);
|
||||
+ }
|
||||
+ if (!onlinePlayers.isEmpty()) {
|
||||
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
|
||||
+ }
|
||||
+
|
||||
+ player.sentListPacket = true;
|
||||
+ player.suppressTrackerForLogin = false;
|
||||
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player);
|
||||
+
|
||||
+ this.sendLevelInfo(player, worldserver1);
|
||||
+
|
||||
+ if (player.level() == worldserver1 && !worldserver1.players().contains(player)) {
|
||||
+ worldserver1.addNewPlayer(player);
|
||||
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||
+ }
|
||||
+
|
||||
+ worldserver1 = player.level();
|
||||
+ java.util.Iterator<net.minecraft.world.effect.MobEffectInstance> iterator = player.getActiveEffects().iterator();
|
||||
+ while (iterator.hasNext()) {
|
||||
+ MobEffectInstance mobeffect = iterator.next();
|
||||
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect, false));
|
||||
+ }
|
||||
+
|
||||
+ if (player.isDeadOrDying()) {
|
||||
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
|
||||
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
|
||||
+ worldserver1.getLightEngine(), null, null, false)
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - replay mod api
|
||||
+
|
||||
public void placeNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie cookie) {
|
||||
player.isRealPlayer = true; // Paper
|
||||
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
|
||||
@@ -296,6 +416,7 @@ public abstract class PlayerList {
|
||||
|
||||
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
||||
this.players.add(player);
|
||||
+ this.realPlayers.add(player); // Leaves - replay api
|
||||
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||
this.playersByUUID.put(player.getUUID(), player);
|
||||
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
|
||||
@@ -515,6 +636,7 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
protected void save(final ServerPlayer player) {
|
||||
+ if (player instanceof org.leavesmc.leaves.replay.ServerPhotographer) return; // Leaves - skip photographer
|
||||
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
||||
player.lastSave = System.nanoTime(); // Folia - region threading - changed to nanoTime tracking
|
||||
this.playerIo.save(player);
|
||||
@@ -529,6 +651,47 @@ public abstract class PlayerList {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Leaves start - replay mod api
|
||||
+ public void removePhotographer(org.leavesmc.leaves.replay.ServerPhotographer entityplayer) {
|
||||
+ ServerLevel worldserver = entityplayer.level();
|
||||
+
|
||||
+ entityplayer.awardStat(Stats.LEAVE_GAME);
|
||||
+
|
||||
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
|
||||
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT);
|
||||
+ }
|
||||
+
|
||||
+ if (server.isSameThread()) entityplayer.doTick();
|
||||
+
|
||||
+ if (this.collideRuleTeamName != null) {
|
||||
+ final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
|
||||
+ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
|
||||
+ if (entityplayer.getTeam() == team && team != null) {
|
||||
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
+ entityplayer.retireScheduler();
|
||||
+ entityplayer.getAdvancements().stopListening();
|
||||
+ this.players.remove(entityplayer);
|
||||
+ // Leaves - guard name removal so a photographer sharing a real player's name won't evict the real player's mapping
|
||||
+ final String nameKey = entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT);
|
||||
+ if (this.playersByName.get(nameKey) == entityplayer) {
|
||||
+ this.playersByName.remove(nameKey);
|
||||
+ }
|
||||
+ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer);
|
||||
+ UUID uuid = entityplayer.getUUID();
|
||||
+ ServerPlayer entityplayer1 = this.playersByUUID.get(uuid);
|
||||
+
|
||||
+ if (entityplayer1 == entityplayer) {
|
||||
+ this.playersByUUID.remove(uuid);
|
||||
+ }
|
||||
+
|
||||
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
|
||||
+ }
|
||||
+ // Leaves end - replay mod api
|
||||
+
|
||||
public net.kyori.adventure.text.@Nullable Component remove(final ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
|
||||
// Paper start - Fix kick event leave message not being sent
|
||||
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
|
||||
@@ -602,6 +765,7 @@ public abstract class PlayerList {
|
||||
player.getBukkitEntity().packetProcessor.close(); // Folia - region threading
|
||||
player.getAdvancements().stopListening();
|
||||
this.players.remove(player);
|
||||
+ this.realPlayers.remove(player); // Leaves - replay api
|
||||
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
this.server.getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
@@ -912,15 +1076,15 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public String[] getPlayerNamesArray() {
|
||||
- List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
|
||||
- String[] names = new String[players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
|
||||
+ List<ServerPlayer> players = new java.util.ArrayList<>(this.realPlayers); // Folia - region threading // Lophine - fakeplayer support
|
||||
+ String[] names = new String[this.realPlayers.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
|
||||
|
||||
- for (int i = 0; i < players.size(); i++) { // Folia - region threading
|
||||
- names[i] = players.get(i).getGameProfile().name(); // Folia - region threading
|
||||
+ for (int i = 0; i < this.realPlayers.size(); i++) { // Folia - region threading // Leaves - only real players
|
||||
+ names[i] = this.realPlayers.get(i).getGameProfile().name(); // Folia - region threading // Leaves - only real players
|
||||
}
|
||||
// Leaves start - fakeplayer support
|
||||
- for (int i = this.players.size(); i < names.length; ++i) {
|
||||
- names[i] = this.server.getBotList().bots.get(i - this.players.size()).gameProfile.name();
|
||||
+ for (int i = this.realPlayers.size(); i < names.length; ++i) { // Leaves - only real players
|
||||
+ names[i] = this.server.getBotList().bots.get(i - this.realPlayers.size()).gameProfile.name(); // Leaves - only real players
|
||||
}
|
||||
// Leaves end - fakeplayer support
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 8a8de7f4d62532709805ebde531dc71ad78fa5c9..167855ad90d0c168a6d49f078ee3409ab84d4bf3 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -261,7 +261,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
public int useItemRemaining;
|
||||
protected int fallFlyTicks;
|
||||
private long lastKineticHitFeedbackTime = -2147483648L;
|
||||
- private BlockPos lastPos;
|
||||
+ protected BlockPos lastPos;
|
||||
private Optional<BlockPos> lastClimbablePos = Optional.empty();
|
||||
private @Nullable DamageSource lastDamageSource;
|
||||
private long lastDamageStamp = Long.MIN_VALUE; // Folia - region threading
|
||||
@@ -0,0 +1,144 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 8 Mar 2026 23:56:06 +0800
|
||||
Subject: [PATCH] Leaves: Creative fly no clip
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/da12a58e8d3bd3cd13b52a60676d5a1e03acd30a/leaves-server/minecraft-patches/features/0049-Creative-fly-no-clip.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java
|
||||
index e302c6198d71782b524391329aa5c89d2b3e0ccf..2312803297321f66c9057bc54ce56dd17ecb6f1f 100644
|
||||
--- a/net/minecraft/world/entity/ExperienceOrb.java
|
||||
+++ b/net/minecraft/world/entity/ExperienceOrb.java
|
||||
@@ -199,7 +199,7 @@ public class ExperienceOrb extends Entity {
|
||||
Player prevTarget = this.followingPlayer; // CraftBukkit - store old target
|
||||
if (this.followingPlayer == null || this.followingPlayer.isSpectator() || this.followingPlayer.distanceToSqr(this) > 64.0) {
|
||||
Player nearestPlayer = this.level().getNearestPlayer(this, 8.0);
|
||||
- if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) {
|
||||
+ if (nearestPlayer != null && !nearestPlayer.isCreativeFlyOrSpectator() && !nearestPlayer.isDeadOrDying()) { // Leaves - creative no clip
|
||||
this.followingPlayer = nearestPlayer;
|
||||
} else {
|
||||
this.followingPlayer = null;
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 38689fa466a20c64f9916ee32a57a9fdb58d9403..7d514537ee38f9b9366692bc969ff503d883aa16 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -279,8 +279,8 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
if (this.cullTask != null) this.cullTask.requestCullSignal(); // Luminol - Ray tracing entity tracker
|
||||
// Luminol end
|
||||
|
||||
- this.noPhysics = this.isSpectator();
|
||||
- if (this.isSpectator() || this.isPassenger()) {
|
||||
+ this.noPhysics = this.isCreativeFlyOrSpectator(); // Leaves - creative no clip
|
||||
+ if (this.isCreativeFlyOrSpectator() || this.isPassenger()) { // Leaves - creative no clip
|
||||
this.setOnGround(false);
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) {
|
||||
Pose desiredPose = this.getDesiredPose();
|
||||
Pose actualPose;
|
||||
- if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) {
|
||||
+ if (this.isCreativeFlyOrSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) { // Leaves - creative no clip
|
||||
actualPose = desiredPose;
|
||||
} else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) {
|
||||
actualPose = Pose.CROUCHING;
|
||||
@@ -535,7 +535,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
this.updateSwingTime();
|
||||
this.yHeadRot = this.getYRot();
|
||||
this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED));
|
||||
- if (this.getHealth() > 0.0F && !this.isSpectator()) {
|
||||
+ if (this.getHealth() > 0.0F && !this.isCreativeFlyOrSpectator()) { // Leaves - creative no clip
|
||||
AABB pickupArea;
|
||||
if (this.isPassenger() && !this.getVehicle().isRemoved()) {
|
||||
pickupArea = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0);
|
||||
@@ -1846,6 +1846,26 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
return this.gameMode() == GameType.SPECTATOR;
|
||||
}
|
||||
|
||||
+ // Leaves start - creative no clip
|
||||
+ public boolean isCreativeFlyOrSpectator() {
|
||||
+ return isSpectator() || (fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && isCreative() && getAbilities().flying);
|
||||
+ }
|
||||
+
|
||||
+ public boolean canSpectatingPlace(final net.minecraft.world.level.LevelReader world, final BlockState state, final BlockPos pos, final net.minecraft.world.phys.shapes.CollisionContext context) {
|
||||
+ if (this.isCreativeFlyOrSpectator()) {
|
||||
+ net.minecraft.world.phys.shapes.VoxelShape voxelShape = state.getCollisionShape(world, pos, context);
|
||||
+ return voxelShape.isEmpty() || world.isUnobstructed(this, voxelShape.move(pos.getX(), pos.getY(), pos.getZ()));
|
||||
+ } else {
|
||||
+ return world.isUnobstructed(state, pos, context);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCollidable(final boolean ignoreClimbing) {
|
||||
+ return !isCreativeFlyOrSpectator() && super.isCollidable(ignoreClimbing);
|
||||
+ }
|
||||
+ // Leaves end - creative no clip
|
||||
+
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
return !this.isSpectator() && super.isPickable();
|
||||
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||
index 2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f..06160c24f1ffbe1445284bc81598cabb3ad20477 100644
|
||||
--- a/net/minecraft/world/item/BlockItem.java
|
||||
+++ b/net/minecraft/world/item/BlockItem.java
|
||||
@@ -158,8 +158,9 @@ public class BlockItem extends Item {
|
||||
Player player = context.getPlayer();
|
||||
// CraftBukkit start
|
||||
Level world = context.getLevel(); // Paper - Cancel hit for vanished players
|
||||
+ CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.placementContext(player); // Leaves - creative no clip
|
||||
boolean canBuild = (!this.mustSurvive() || stateForPlacement.canSurvive(world, context.getClickedPos()))
|
||||
- && world.checkEntityCollision(stateForPlacement, player, CollisionContext.placementContext(player), context.getClickedPos(), true); // Paper - Cancel hit for vanished players
|
||||
+ && ((fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, stateForPlacement, context.getClickedPos(), collisionContext) : world.checkEntityCollision(stateForPlacement, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip
|
||||
org.bukkit.entity.Player bukkitPlayer = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
|
||||
|
||||
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(
|
||||
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
index cb0a4a9865df69e5504a86de6c144bc4450bd19a..a40a98bb48bb14c49670ba55d2a2e8d7e9d0d178 100644
|
||||
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||
@@ -44,7 +44,7 @@ public class StandingAndWallBlockItem extends BlockItem {
|
||||
// return stateForPlacement != null && level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()) ? stateForPlacement : null;
|
||||
// CraftBukkit start
|
||||
if (stateForPlacement != null) {
|
||||
- boolean defaultReturn = level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty());
|
||||
+ boolean defaultReturn = (fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig.enabled && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(level, stateForPlacement, pos, CollisionContext.empty()) : level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); // Leaves - creative no clip
|
||||
org.bukkit.entity.Player player = (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer serverPlayer) ? serverPlayer.getBukkitEntity() : null;
|
||||
|
||||
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), pos), player, stateForPlacement.asBlockData(), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
|
||||
diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
index 6205f52ecad24f80d21b924945c5ff06c6704aca..d84159df4d2a0379ffbb6bdb0807b4a02dbec71e 100644
|
||||
--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
@@ -153,7 +153,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
||||
List<Entity> entities = level.getEntities(null, aabb);
|
||||
if (!entities.isEmpty()) {
|
||||
for (Entity entity : entities) {
|
||||
- if (entity.getPistonPushReaction() != PushReaction.IGNORE) {
|
||||
+ if (entity.getPistonPushReaction() != PushReaction.IGNORE && !(entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator())) { // Leaves - creative no clip
|
||||
entity.move(
|
||||
MoverType.SHULKER_BOX,
|
||||
new Vec3(
|
||||
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
index 2ecb10fe97d15954e44c61247eabc8818eb16f34..22663ad55f669081b43644ad2cf1bd4aac48b745 100644
|
||||
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
|
||||
@@ -168,7 +168,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
dz = movement.getStepZ();
|
||||
}
|
||||
|
||||
- entity.setDeltaMovement(dx, dy, dz);
|
||||
+ if (!(entity instanceof net.minecraft.world.entity.player.Player player) || !player.isCreativeFlyOrSpectator()) entity.setDeltaMovement(dx, dy, dz); // Leaves - creative no clip
|
||||
// Paper - EAR items stuck in slime pushed by a piston
|
||||
entity.activatedTick = Math.max(entity.activatedTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 10); // Folia - region threading
|
||||
entity.activatedImmunityTick = Math.max(entity.activatedImmunityTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 10); // Folia - region threading
|
||||
@@ -204,6 +204,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
|
||||
}
|
||||
|
||||
private static void moveEntityByPiston(final Direction pistonDirection, final Entity entity, final double delta, final Direction movement) {
|
||||
+ if (entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator()) return; // Leaves - creative no clip
|
||||
NOCLIP.set(pistonDirection);
|
||||
Vec3 previousPos = entity.position();
|
||||
entity.move(MoverType.PISTON, new Vec3(delta * movement.getStepX(), delta * movement.getStepY(), delta * movement.getStepZ()));
|
||||
@@ -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 d036018ee64995ee754296014888ee70c0ea5ab3..aa782c6441cdce3eb39aefb28d40f3b1970d4e62 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -239,8 +239,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
changed |= action.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, entity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
|
||||
+ if (woolColor != null) {
|
||||
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||
+ changed |= suckInItems(level, entity);
|
||||
+ if (!changed) {
|
||||
+ break;
|
||||
+ } else {
|
||||
+ woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - Wool hopper counter
|
||||
+
|
||||
if (changed) {
|
||||
entity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
|
||||
+ // Leaves start - Wool hopper counter
|
||||
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
|
||||
+ entity.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
|
||||
@@ -491,6 +513,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
// Paper end - Perf: Optimize Hoppers
|
||||
|
||||
private static boolean ejectItems(final Level level, final BlockPos blockPos, final HopperBlockEntity self) {
|
||||
+ // Leaves start - hopper counter
|
||||
+ if (org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
|
||||
+ if (woolHopperCounter(level, blockPos, level.getBlockState(blockPos), HopperBlockEntity.getContainerAt(level, blockPos))) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - hopper counter
|
||||
Container container = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? self.getInsertInventory(level) : getAttachedContainer(level, blockPos, self); // Leaves - Lithium Sleeping Block Entity
|
||||
if (container == null) {
|
||||
return false;
|
||||
@@ -512,6 +541,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.getServer(), itemstack);
|
||||
+ container.setItem(i, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Leaves end - hopper counter
|
||||
+
|
||||
private static int[] getSlots(final Container container, final Direction direction) {
|
||||
if (container instanceof WorldlyContainer worldlyContainer) {
|
||||
return worldlyContainer.getSlotsForFace(direction);
|
||||
@@ -606,6 +655,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
|
||||
public static boolean addItem(final Container container, final ItemEntity entity) {
|
||||
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && entity.isRemoved()) return false; // Leaves - Wool hopper counter
|
||||
boolean changed = false;
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
|
||||
@@ -0,0 +1,186 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 3 Dec 2025 16:28:34 +0800
|
||||
Subject: [PATCH] Global Entities Counter
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 0cf5815672ac62d8caf7f18165be1f0f8e067aed..64d407c5a6140a7e5dc47a8e304b4c00602e2bdd 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -558,6 +558,9 @@ public final class RegionizedWorldData {
|
||||
public final Map<Long, ChunkSectionItemEntityMovementTracker> itemEntityMovementTrackerMap = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>();
|
||||
// Luminol end
|
||||
|
||||
+ public int uniqueId = -1; // Lophine - Global Entities Counter
|
||||
+ public boolean underGlobalEntitiesCounter = false; // Lophine - Global Entities Counter
|
||||
+
|
||||
public final TickRegions.TickRegionData regionData;
|
||||
|
||||
public RegionizedWorldData(final ServerLevel world, final TickRegions.TickRegionData regionData) {
|
||||
@@ -570,6 +573,15 @@ public final class RegionizedWorldData {
|
||||
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
|
||||
this.regionData = regionData;
|
||||
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ uniqueId = fun.bm.lophine.utils.EntitiesCounterUtil.generateUniqueId();
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(world, spawnChunkTracker, uniqueId);
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(world, loadedEntities, uniqueId);
|
||||
+ underGlobalEntitiesCounter = true;
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
+
|
||||
// tasks may be drained before the region ticks, so we must set up the tick data early just in case
|
||||
this.updateTickData();
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 27389ff98942e27c2a877ea5b671caa31353d18c..e9e5f929d638d3ddf279423d3e23b3f824ad7df2 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -513,6 +513,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
this.chunkMap.tick(haveTime);
|
||||
profiler.pop();
|
||||
this.clearCache();
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData();
|
||||
+ if (regionizedWorldData != null) {
|
||||
+ if (regionizedWorldData.underGlobalEntitiesCounter) {
|
||||
+ if (regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.onWorldDataUnload(level, regionizedWorldData.uniqueId);
|
||||
+ regionizedWorldData.underGlobalEntitiesCounter = false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (!regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(level, regionizedWorldData.spawnChunkTracker, regionizedWorldData.uniqueId);
|
||||
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(level, (ca.spottedleaf.moonrise.common.list.ReferenceList<Entity>) regionizedWorldData.getLoadedEntities(), regionizedWorldData.uniqueId);
|
||||
+ regionizedWorldData.underGlobalEntitiesCounter = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
}
|
||||
|
||||
private void tickChunks() {
|
||||
@@ -577,7 +596,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
spawnCookie = NaturalSpawner.createState(chunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||
} else {
|
||||
- spawnCookie = NaturalSpawner.createState(chunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ spawnCookie = fun.bm.lophine.utils.EntitiesCounterUtil.runRemainingTasks(level, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ } else {
|
||||
+ spawnCookie = NaturalSpawner.createState(chunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
}
|
||||
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); } // Folia - profiler
|
||||
// Paper end - Optional per player mob spawns
|
||||
@@ -585,7 +610,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
boolean doMobSpawning = this.level.getGameRules().get(GameRules.SPAWN_MOBS) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threading
|
||||
int tickSpeed = this.level.getGameRules().get(GameRules.RANDOM_TICK_SPEED);
|
||||
List<MobCategory> spawningCategories;
|
||||
- if (doMobSpawning && (this.spawnEnemies || this.spawnFriendlies)) { // Paper
|
||||
+ if (spawnCookie != null && doMobSpawning && (this.spawnEnemies || this.spawnFriendlies)) { // Paper // Lophine - Global Entities Counter
|
||||
// Paper start - PlayerNaturallySpawnCreaturesEvent
|
||||
for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading
|
||||
int chunkRange = Math.min(level.spigotConfig.mobSpawnRange, player.getBukkitEntity().getViewDistance());
|
||||
@@ -645,7 +670,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
this.level.tickThunder(chunk);
|
||||
}
|
||||
|
||||
- if (!spawningCategories.isEmpty()) {
|
||||
+ if (spawnCookie != null && !spawningCategories.isEmpty()) { // Lophine - Global Entities Counter
|
||||
if (this.level.getWorldBorder().isWithinBounds(chunkPos)) { // Paper - rewrite chunk system
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk, spawnCookie, spawningCategories);
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c51b0075cd650085cd991bc89396f605cb520442..fe9c292ec4b550d8456eb6d1f0dbf6bc1dd47c54 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -808,6 +808,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
public void tick(BooleanSupplier haveTime, final io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking
|
||||
+ // Lophine start - Global Entities Counter
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ if (fun.bm.lophine.utils.EntitiesCounterUtil.canRunNewTask(this)) fun.bm.lophine.utils.EntitiesCounterUtil.tick(this);
|
||||
+ }
|
||||
+ // Lophine end - Global Entities Counter
|
||||
final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking
|
||||
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index fc29654dd7ee3329edf1ccf705f45631d0ecc079..5cad076041ed008670cfd8e51a3601c2ef972ad1 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -813,6 +813,44 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
}
|
||||
}
|
||||
} else {
|
||||
+ // Lophine start - fix some bug if player is cross scheduler >> to remove monster if the region don't have any valid player
|
||||
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||
+ List<net.minecraft.server.level.ServerPlayer> playerList = this.level().getServer().getPlayerList().getPlayers();
|
||||
+ if (!playerList.isEmpty()) {
|
||||
+ double d = -1.0;
|
||||
+ Vec3 vec3 = null;
|
||||
+ for (net.minecraft.server.level.ServerPlayer player1 : playerList) {
|
||||
+ if (player1.level() != this.level()) continue;
|
||||
+ double d1 = player1.distanceToSqr(this.position());
|
||||
+ if (d == -1.0 || d1 < d) {
|
||||
+ d = d1;
|
||||
+ vec3 = player1.position();
|
||||
+ }
|
||||
+ }
|
||||
+ if (vec3 != null) {
|
||||
+ // copy from PaperMC
|
||||
+ // Paper start - Configurable despawn distances
|
||||
+ final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory());
|
||||
+ final io.papermc.paper.configuration.type.DespawnRange.Shape shape = this.level().paperConfig().entities.spawning.despawnRangeShape;
|
||||
+ final double dy = Math.abs(vec3.y - this.getY());
|
||||
+ final double dySqr = Mth.square(dy);
|
||||
+ final double dxSqr = Mth.square(vec3.x - this.getX());
|
||||
+ final double dzSqr = Mth.square(vec3.z - this.getZ());
|
||||
+ final double distanceSquared = dxSqr + dzSqr + dySqr;
|
||||
+ // Despawn if hard/soft limit is exceeded
|
||||
+ if (despawnRangePair.hard().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy) && this.removeWhenFarAway(distanceSquared)) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
+ }
|
||||
+
|
||||
+ if (despawnRangePair.soft().shouldDespawn(shape, dxSqr, dySqr, dzSqr, dy)) {
|
||||
+ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && this.removeWhenFarAway(distanceSquared)) {
|
||||
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Lophine end
|
||||
this.noActionTime = 0;
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index b3b8160927147468c1dd4a30fac51f96a9d60c9a..cd20d10ee4cd2fe98131c9a93367ae133f96b8d4 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -121,7 +121,7 @@ public final class NaturalSpawner {
|
||||
return new NaturalSpawner.SpawnState(spawnableChunkCount, mobCounts, spawnPotential, localMobCapCalculator);
|
||||
}
|
||||
|
||||
- private static Biome getRoughBiome(final BlockPos pos, final ChunkAccess chunk) {
|
||||
+ public static Biome getRoughBiome(final BlockPos pos, final ChunkAccess chunk) { // Lophine - protected -> public
|
||||
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ public final class NaturalSpawner {
|
||||
private @Nullable EntityType<?> lastCheckedType;
|
||||
private double lastCharge;
|
||||
|
||||
- private SpawnState(
|
||||
+ public SpawnState( // Lophine - protected -> public
|
||||
final int spawnableChunkCount,
|
||||
final Object2IntOpenHashMap<MobCategory> mobCategoryCounts,
|
||||
final PotentialCalculator spawnPotential,
|
||||
@@ -8,7 +8,7 @@ Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
bdlvl <bdlvl@blendreams.cn>
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
index 22c038e6556d9911e1eaedf71d7b86843af89c16..f5574eb883b1ee8747acc42832bc88ae03e27b67 100644
|
||||
index fcdfd4f6de5e1c2d5e80c7f3d8cb0b33a62d257d..6eaa4e9bd1ecbfa531313ce1f470d55edf31b467 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
|
||||
@@ -593,7 +593,7 @@ public class Metrics {
|
||||
@@ -35,27 +35,20 @@ index 22c038e6556d9911e1eaedf71d7b86843af89c16..f5574eb883b1ee8747acc42832bc88ae
|
||||
metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> {
|
||||
Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
index 22125dbe1765f930fe10fe420be1c275ec553139..d5b070d1a3d84e228960dacd614e0f1abe968e79 100644
|
||||
index a5f2e4454258886536251288c3694f58386c7420..28371ecf31d5fc280aaa03ed9a86f5b565cf32f6 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
|
||||
@@ -35,7 +35,7 @@ public class PaperVersionFetcher implements VersionFetcher {
|
||||
private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
@@ -40,8 +40,8 @@ public class PaperVersionFetcher implements VersionFetcher {
|
||||
private static final ComponentLogger COMPONENT_LOGGER = ComponentLogger.logger(LogManager.getRootLogger().getName());
|
||||
private static final int DISTANCE_ERROR = -1;
|
||||
private static final int DISTANCE_UNKNOWN = -2;
|
||||
- private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Luminol"; //Luminol
|
||||
+ private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Lophine"; //Luminol // Lophine
|
||||
|
||||
@Override
|
||||
public long getCacheTime() {
|
||||
@@ -49,7 +49,7 @@ public class PaperVersionFetcher implements VersionFetcher {
|
||||
if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) {
|
||||
updateMessage = text("You are running a development version without access to version information", color(0xFF5300));
|
||||
} else {
|
||||
- updateMessage = getUpdateStatusMessage("LuminolMC/Luminol", build); // Folia // Luminol
|
||||
+ updateMessage = getUpdateStatusMessage("LuminolMC/Lophine", build); // Folia // Luminol // Lophine
|
||||
}
|
||||
final @Nullable Component history = this.getHistory();
|
||||
|
||||
- private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Luminol"; // Luminol
|
||||
- private static final String REPOSITORY = "LuminolMC/Luminol"; // Luminol
|
||||
+ private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Lophine"; // Luminol // Lophine
|
||||
+ private static final String REPOSITORY = "LuminolMC/Lophine"; // Luminol // Lophine
|
||||
private static final ServerBuildInfo BUILD_INFO = ServerBuildInfo.buildInfo();
|
||||
private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://papermc.io)";
|
||||
private static final Gson GSON = new Gson();
|
||||
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
|
||||
index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5effe76734b4 100644
|
||||
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
|
||||
@@ -90,19 +83,6 @@ index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5eff
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..2c546d470013d4daf3ddf427ab4bda1b51d6e641 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
|
||||
@@ -11,7 +11,7 @@ public final class Versioning {
|
||||
public static String getBukkitVersion() {
|
||||
String result = "Unknown-Version";
|
||||
|
||||
- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.luminol/luminol-api/pom.properties"); // Folia //Luminol
|
||||
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/fun.bm.lophine/lophine-api/pom.properties"); // Folia //Luminol
|
||||
Properties properties = new Properties();
|
||||
|
||||
if (stream != null) {
|
||||
diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png
|
||||
index 2b6037aab645e303df6edbbc8af34dc4b4a55bc5..76ea89f23e6d2a42806c5d5d29b415d325e1ee82 100644
|
||||
GIT binary patch
|
||||
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Suisuroru <qwertyuiop14077@qq.com>
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 20 Feb 2025 01:00:29 +0800
|
||||
Subject: [PATCH] Purpur: Barrels and enderchests 6 rows
|
||||
|
||||
Co-authored by: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/purpur-server/paper-patches/features/0003-Barrels-and-enderchests-6-rows.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
||||
Co-authored by: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/purpur-server/paper-patches/features/0003-Barrels-and-enderchests-6-rows.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/LICENSE)
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
index 2f41a92465b9da28e026297cc3528898bb1c8412..168301a2f1c3081ae15d3695c2dcc72b4538cdfb 100644
|
||||
@@ -41,15 +41,15 @@ index 2f41a92465b9da28e026297cc3528898bb1c8412..168301a2f1c3081ae15d3695c2dcc72b
|
||||
case DROPPER:
|
||||
this.delegate = new DispenserMenu(windowId, bottom, top);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index f850e6cea92edc87ed54cf54488b5ebb606913ed..f4db38de4348fb03db0b769bd5b5993184dd4abb 100644
|
||||
index 9d5fe6fc727948955d89f9ed5e181185393a9611..5e5a4e48b2a96c355256b8f8bfcc09225d562944 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -84,7 +84,7 @@ public class CraftInventory implements Inventory {
|
||||
@@ -85,7 +85,7 @@ public class CraftInventory implements Inventory {
|
||||
|
||||
@Override
|
||||
public void setContents(ItemStack[] items) {
|
||||
- Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize());
|
||||
+ // Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize()); // Purpur - Barrels and enderchests 6 rows
|
||||
+ // Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize()); // Purpur - Barrels and enderchests 6 rows
|
||||
|
||||
for (int i = 0; i < this.getSize(); i++) {
|
||||
if (i >= items.length) {
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 22 Nov 2025 01:43:26 +0800
|
||||
Subject: [PATCH] Add cancel task by task id in FoliaGlobalRegionScheduler
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||
index 14ffbcb66006878eacf310547dad53718f8308eb..f20f2735fbb4d1e38d576eafe18a0054a45aa59e 100644
|
||||
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||
@@ -16,6 +16,8 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
private long tickCount = 0L;
|
||||
private final Object stateLock = new Object();
|
||||
private final Long2ObjectOpenHashMap<List<GlobalScheduledTask>> tasksByDeadline = new Long2ObjectOpenHashMap<>();
|
||||
+ private int lastTaskId = 1; // Lophine - add task id
|
||||
+ private final Object stateLockForTaskId = new Object(); // Lophine - add task id
|
||||
|
||||
public void tick() {
|
||||
final List<GlobalScheduledTask> run;
|
||||
@@ -64,7 +66,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
|
||||
}
|
||||
|
||||
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task);
|
||||
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task, this.getNextTaskId()); // Lophine - add task id
|
||||
|
||||
this.scheduleInternal(ret, delayTicks);
|
||||
|
||||
@@ -91,7 +93,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
|
||||
}
|
||||
|
||||
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task);
|
||||
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task, this.getNextTaskId()); // Lophine - add task id
|
||||
|
||||
this.scheduleInternal(ret, initialDelayTicks);
|
||||
|
||||
@@ -133,7 +135,34 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
- private final class GlobalScheduledTask implements ScheduledTask, Runnable {
|
||||
+ // Lophine start - add cancel task by task id
|
||||
+ @Override
|
||||
+ public void cancelTask(final int taskId) {
|
||||
+ synchronized (this.stateLock) {
|
||||
+ for (final List<GlobalScheduledTask> tasks : this.tasksByDeadline.values()) {
|
||||
+ for (final GlobalScheduledTask task : tasks) {
|
||||
+ if (task.getTaskId() == taskId) {
|
||||
+ task.cancel();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private int getNextTaskId() {
|
||||
+ synchronized (this.stateLockForTaskId) {
|
||||
+ if (this.lastTaskId == Integer.MAX_VALUE) {
|
||||
+ this.lastTaskId = 1;
|
||||
+ } else {
|
||||
+ ++this.lastTaskId;
|
||||
+ }
|
||||
+ }
|
||||
+ return this.lastTaskId;
|
||||
+ }
|
||||
+ // Lophine end - add cancel task by task id
|
||||
+
|
||||
+ public final class GlobalScheduledTask implements ScheduledTask, Runnable { // Lophine - private -> public
|
||||
|
||||
private static final int STATE_IDLE = 0;
|
||||
private static final int STATE_EXECUTING = 1;
|
||||
@@ -145,13 +174,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
private final long repeatDelay; // in ticks
|
||||
private Consumer<ScheduledTask> run;
|
||||
private volatile int state;
|
||||
+ private final int taskId; // Lophine - add task id
|
||||
|
||||
private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
|
||||
|
||||
- private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run) {
|
||||
+ private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run, int taskId) { // Lophine - add task id
|
||||
this.plugin = plugin;
|
||||
this.repeatDelay = repeatDelay;
|
||||
this.run = run;
|
||||
+ this.taskId = taskId; // Lophine - add task id
|
||||
}
|
||||
|
||||
private final int getStateVolatile() {
|
||||
@@ -262,5 +293,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Lophine start - add task id
|
||||
+ public int getTaskId() {
|
||||
+ return taskId;
|
||||
+ }
|
||||
+ // Lophine end - add task id
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,17 +1,17 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 3 Aug 2025 15:57:08 +0800
|
||||
Subject: [PATCH] Leaves: Leaves Protocol Core
|
||||
Subject: [PATCH] Leaves: Leaves Base Protocol Core
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch)
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e7f4a313ff0d2469dd7feae36304f0c8994cba1/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch)
|
||||
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 4dde33c872d463bf17ba03e926de90e6988444b2..de72f36bd22e2c7452b9c3ee40657f6119ca70b3 100644
|
||||
index 20bebf72768968d90f27f812456796cf81f46626..479bbc4a63c237c055f6b4d659c598e9fadd512a 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 {
|
||||
@@ -483,6 +483,7 @@ public final class CraftServer implements Server {
|
||||
this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
|
||||
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
||||
if (false) this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark // Luminol - Force disable builtin spark
|
||||
@@ -19,7 +19,7 @@ index 4dde33c872d463bf17ba03e926de90e6988444b2..de72f36bd22e2c7452b9c3ee40657f61
|
||||
}
|
||||
|
||||
public boolean getCommandBlockOverride(String command) {
|
||||
@@ -1115,6 +1116,7 @@ public final class CraftServer implements Server {
|
||||
@@ -1057,6 +1058,7 @@ public final class CraftServer implements Server {
|
||||
if (false) this.spark.registerCommandBeforePlugins(this); // Paper - spark // Luminol - Force disable builtin spark
|
||||
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
||||
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
||||
@@ -0,0 +1,13 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 17:47:42 +0800
|
||||
Subject: [PATCH] LeavesHooks
|
||||
|
||||
|
||||
diff --git a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||
index e57c3ca79677b1dfe7cf3db36f0406de7ea5bd0a..86edd824ec42e550dd1419fd57d93a21fe2d648d 100644
|
||||
--- a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||
+++ b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||
@@ -1 +1 @@
|
||||
-ca.spottedleaf.moonrise.paper.PaperHooks
|
||||
+org.leavesmc.leaves.region.LeavesHooks
|
||||
+21
-21
@@ -41,22 +41,22 @@ index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6
|
||||
if (!registration.getPlugin().isEnabled()) {
|
||||
continue;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
index 0a10f49ee410d93e95ceb90108200a1a9d12b54b..d2eee37d810a6d5cf514bc71dea66a4d2b0d09e2 100644
|
||||
index 5339ff469a38d35e72ea7227503a84395462f84a..d75b4ecb24f2ea42afc82ac255775d8f35121fe5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
@@ -423,6 +423,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
@@ -373,6 +373,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Entity> T addEntity(T entity) {
|
||||
Preconditions.checkArgument(!entity.isInWorld(), "Entity has already been added to a world");
|
||||
+ Preconditions.checkState(!(entity instanceof org.leavesmc.leaves.entity.bot.CraftBot), "[Leaves] Fakeplayers do not support changing world, Please use leaves fakeplayer-api instead!");
|
||||
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle();
|
||||
if (nmsEntity.level() != this.getHandle().getLevel()) {
|
||||
nmsEntity = nmsEntity.teleport(new TeleportTransition(this.getHandle().getLevel(), nmsEntity, TeleportTransition.DO_NOTHING));
|
||||
throw new IllegalArgumentException(entity + " wasn't created with this world, you must create the entity with the world you want to add it to.");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c3c89e815 100644
|
||||
index 479bbc4a63c237c055f6b4d659c598e9fadd512a..054d9f4a09035771a329d6d561249d206b5dbee3 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 {
|
||||
@@ -303,6 +303,7 @@ public final class CraftServer implements Server {
|
||||
private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer;
|
||||
public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
|
||||
private final ServerConfiguration serverConfig = new PaperServerConfiguration();
|
||||
@@ -64,7 +64,7 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
|
||||
|
||||
// Paper start - Folia region threading API
|
||||
private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
|
||||
@@ -498,6 +499,7 @@ public final class CraftServer implements Server {
|
||||
@@ -484,6 +485,7 @@ public final class CraftServer implements Server {
|
||||
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
||||
if (false) this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark // Luminol - Force disable builtin spark
|
||||
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol
|
||||
@@ -72,7 +72,7 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
|
||||
}
|
||||
|
||||
public boolean getCommandBlockOverride(String command) {
|
||||
@@ -1482,7 +1484,7 @@ public final class CraftServer implements Server {
|
||||
@@ -1377,7 +1379,7 @@ public final class CraftServer implements Server {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,9 +81,9 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3260,6 +3262,13 @@ public final class CraftServer implements Server {
|
||||
this.console.addPluginAllowingSleep(plugin.getName(), value);
|
||||
@@ -3055,6 +3057,13 @@ public final class CraftServer implements Server {
|
||||
}
|
||||
// Leaves end - Feature API
|
||||
|
||||
+ // Leaves start - Bot API
|
||||
+ @Override
|
||||
@@ -96,10 +96,10 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
|
||||
/**
|
||||
* Gets the TPS from the region which owns the specified location, or {@code null} if no region owns
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e2630a29409 100644
|
||||
index 03ad9254c4b5556119fe73d533ceac7073b8fe74..fd2e24b6219219fa1fe7d2ba1d877ee4c24676ca 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -249,7 +249,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@@ -255,7 +255,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
@@ -108,7 +108,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1279,9 +1279,9 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@@ -1126,9 +1126,9 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
|
||||
@Override
|
||||
public List<Player> getPlayers() {
|
||||
@@ -120,7 +120,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
|
||||
HumanEntity bukkitEntity = human.getBukkitEntity();
|
||||
|
||||
if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) {
|
||||
@@ -1988,7 +1988,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@@ -1628,7 +1628,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
public void playSound(final net.kyori.adventure.sound.Sound sound) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
final long seed = sound.seed().orElseGet(this.world.getRandom()::nextLong);
|
||||
@@ -129,7 +129,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
|
||||
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player.getX(), player.getY(), player.getZ(), seed, null));
|
||||
}
|
||||
}
|
||||
@@ -2016,7 +2016,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@@ -1656,7 +1656,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
|
||||
final long seed = sound.seed().orElseGet(this.getHandle().getRandom()::nextLong);
|
||||
if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) {
|
||||
@@ -138,20 +138,20 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
|
||||
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player, seed, null));
|
||||
}
|
||||
} else if (emitter instanceof CraftEntity craftEntity) {
|
||||
@@ -2248,7 +2248,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
@@ -1779,7 +1779,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType());
|
||||
}
|
||||
this.getHandle().sendParticlesSource(
|
||||
- receivers == null ? this.getHandle().players() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API
|
||||
+ receivers == null ? this.getHandle().realPlayers() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API // Leaves - skip
|
||||
- receivers == null ? this.getHandle().players() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API
|
||||
+ receivers == null ? this.getHandle().realPlayers() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API // Leaves - skip
|
||||
sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API
|
||||
CraftParticle.createParticleParam(particle, data), // Particle
|
||||
force,
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 852e1ffef6a022caad7c8eff34091e50112a2290..8eb5d014d9ed688ffebaffb4ce0bb40896961a04 100644
|
||||
index d43b1a6e6a8ac2a21b0a048e838115b0403170dd..42c2c6a05645e5aef26e9d3a91ad93563a297ca3 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -126,6 +126,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
@@ -127,6 +127,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return new CraftHumanEntity(server, (net.minecraft.world.entity.player.Player) entity);
|
||||
}
|
||||
|
||||
@@ -161,10 +161,10 @@ 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 e040f9a7c9451fbe547dda56952410047a99ddc0..05753de195bd7f4ac2952183662a8cc9ec8f4ba0 100644
|
||||
index 23882dbe5fdfe9f0cf98a13791f70fe83393639d..41cf8145a6a5f1542e06af522201fccef1d5f07d 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 {
|
||||
@@ -1004,7 +1004,11 @@ public class CraftEventFactory {
|
||||
event.setKeepInventory(keepInventory);
|
||||
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
|
||||
populateFields(victim, event); // Paper - make cancellable
|
||||
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 15:55:47 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
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/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||
@@ -57,7 +57,7 @@ class PaperEventManager {
|
||||
}
|
||||
|
||||
// Leaves start - skip bot
|
||||
- if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot) {
|
||||
+ if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && (playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot || playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.photographer.Photographer)) { // Leaves - and photographer
|
||||
return;
|
||||
}
|
||||
// Leaves end - skip bot
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 054d9f4a09035771a329d6d561249d206b5dbee3..8fc75ef37f273433fb11cc1e0beee87484c3e18f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -304,6 +304,7 @@ public final class CraftServer implements Server {
|
||||
public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
|
||||
private final ServerConfiguration serverConfig = new PaperServerConfiguration();
|
||||
private final org.leavesmc.leaves.entity.bot.CraftBotManager botManager; // Leaves
|
||||
+ private final org.leavesmc.leaves.entity.photographer.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.photographer.CraftPhotographerManager(); // Leaves
|
||||
|
||||
// Paper start - Folia region threading API
|
||||
private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
|
||||
@@ -398,7 +399,7 @@ public final class CraftServer implements Server {
|
||||
public CraftServer(DedicatedServer console, PlayerList playerList) {
|
||||
this.console = console;
|
||||
this.playerList = (DedicatedPlayerList) playerList;
|
||||
- this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<ServerPlayer, CraftPlayer>() {
|
||||
+ this.playerView = Collections.unmodifiableList(Lists.transform(playerList.realPlayers, new Function<ServerPlayer, CraftPlayer>() { // Leaves - replay api
|
||||
@Override
|
||||
public CraftPlayer apply(ServerPlayer player) {
|
||||
return player.getBukkitEntity();
|
||||
@@ -3128,4 +3129,11 @@ public final class CraftServer implements Server {
|
||||
}
|
||||
}
|
||||
// Folia end - region TPS API
|
||||
+
|
||||
+ // Leaves start - replay mod api
|
||||
+ @Override
|
||||
+ public org.leavesmc.leaves.entity.photographer.CraftPhotographerManager getPhotographerManager() {
|
||||
+ return photographerManager;
|
||||
+ }
|
||||
+ // Leaves end - replay mod api
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 42c2c6a05645e5aef26e9d3a91ad93563a297ca3..759d54f1f012461fc322d452bb26f7fd6e601039 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -128,6 +128,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
}
|
||||
|
||||
if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { return new org.leavesmc.leaves.entity.bot.CraftBot(server, bot); }
|
||||
+ if (entity instanceof org.leavesmc.leaves.replay.ServerPhotographer photographer) { return new org.leavesmc.leaves.entity.photographer.CraftPhotographer(server, photographer); }
|
||||
|
||||
// Special case complex part, since there is no extra entity type for them
|
||||
if (entity instanceof EnderDragonPart complexPart) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 47926ff2fba43bb83e2d9747420a526cce8ebe65..e72cd3c9919978a0ed91614d51d018bfb2cdb900 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -2086,7 +2086,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
|
||||
|
||||
@Override
|
||||
public boolean canSee(Player player) {
|
||||
- return this.canSee((org.bukkit.entity.Entity) player);
|
||||
+ return !(player instanceof org.leavesmc.leaves.entity.photographer.Photographer) && this.canSee((org.bukkit.entity.Entity) player); // Leaves - skip photographer
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index fa3e2bf2b31ca5173d71082e93eb7eaa4faa2816..bd3c4eb10489f13562b31f4b809e80b19717bc25 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -347,7 +347,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
|
||||
}
|
||||
|
||||
- MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> {
|
||||
+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().realPlayers.forEach(player -> { // Leaves - only real players
|
||||
player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements());
|
||||
player.getAdvancements().flushDirty(player, false);
|
||||
});
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||
index 25aae550dcdcef2df268d0dd99bdcc9bbd49fcf8..83af50de50a03e164d572f3c3466b6d0b42ed138 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||
@@ -23,7 +23,7 @@ public class LazyPlayerSet extends LazyHashSet<Player> {
|
||||
}
|
||||
|
||||
public static Set<Player> makePlayerSet(final MinecraftServer server) {
|
||||
- List<ServerPlayer> players = server.getPlayerList().players;
|
||||
+ List<ServerPlayer> players = server.getPlayerList().realPlayers; // Leaves - only real players
|
||||
Set<Player> reference = new HashSet<>(players.size());
|
||||
for (ServerPlayer player : players) {
|
||||
reference.add(player.getBukkitEntity());
|
||||
@@ -0,0 +1,8 @@
|
||||
package fun.bm.lophine;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class LophineLogger {
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package fun.bm.lophine.carpet;
|
||||
|
||||
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public final class CarpetCalculatorCompatHelper {
|
||||
|
||||
public static boolean handleChat(ServerPlayer player, String rawMessage) {
|
||||
if (!GeneralCompatConfig.simpleInGameCalculator || !rawMessage.startsWith("=")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String expression = rawMessage.substring(1).trim();
|
||||
if (expression.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Component response;
|
||||
try {
|
||||
double result = new ExpressionBuilder(expression).build().evaluate();
|
||||
response = Component.literal(expression + " = " + formatNumber(result)).withStyle(ChatFormatting.YELLOW);
|
||||
} catch (RuntimeException exception) {
|
||||
response = Component.literal("Calculator error: " + exception.getMessage()).withStyle(ChatFormatting.RED);
|
||||
}
|
||||
|
||||
Component scheduledResponse = response;
|
||||
player.getBukkitEntity().taskScheduler.schedule((ServerPlayer scheduledPlayer) -> scheduledPlayer.sendSystemMessage(scheduledResponse), null, 1L);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String formatNumber(double value) {
|
||||
if (Double.isFinite(value) && Math.rint(value) == value && value >= Long.MIN_VALUE && value <= Long.MAX_VALUE) {
|
||||
return Long.toString((long) value);
|
||||
}
|
||||
return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
package fun.bm.lophine.carpet;
|
||||
|
||||
import fun.bm.lophine.carpet.config.modules.CoreConfig;
|
||||
import fun.bm.lophine.carpet.config.modules.CounterCompatConfig;
|
||||
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
|
||||
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||
import fun.bm.lophine.config.modules.experiment.CommandConfig;
|
||||
import fun.bm.lophine.config.modules.experiment.RedStoneConfig;
|
||||
import fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig;
|
||||
import fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig;
|
||||
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||
import fun.bm.lophine.config.modules.function.LanguageConfig;
|
||||
import fun.bm.lophine.config.modules.function.WoolHopperCounterConfig;
|
||||
import fun.bm.lophine.protocol.CarpetLoggerProtocol;
|
||||
import me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig;
|
||||
import org.leavesmc.leaves.bot.ServerBot;
|
||||
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// WARNING: THIS FILE NEED TO FULLY REWRITTEN
|
||||
public final class CarpetCompatSync {
|
||||
private static boolean init = false;
|
||||
|
||||
public static void apply() {
|
||||
if (init) return;
|
||||
if (CoreConfig.enabled) {
|
||||
applyGeneralRules();
|
||||
applyFakePlayerRules();
|
||||
applyCounterRules();
|
||||
}
|
||||
CarpetLoggerProtocol.refreshConfiguredDefaults(!init);
|
||||
registerProtocolRules();
|
||||
init = true;
|
||||
}
|
||||
|
||||
private static void applyGeneralRules() {
|
||||
LanguageConfig.lang = GeneralCompatConfig.language;
|
||||
UpdateSuppressionCrashFixConfig.enabled = GeneralCompatConfig.amsUpdateSuppressionCrashFix || GeneralCompatConfig.yeetUpdateSuppressionCrash;
|
||||
RedStoneConfig.redstoneIgnoreUpwardsUpdate = GeneralCompatConfig.dustTrapdoorReintroduced;
|
||||
RedStoneConfig.cce = GeneralCompatConfig.shulkerBoxCCEReintroduced;
|
||||
RedStoneConfig.instantBlockUpdater = GeneralCompatConfig.instantBlockUpdaterReintroduced;
|
||||
CommandConfig.tick = GeneralCompatConfig.commandTick;
|
||||
CreativeFlyNoClipConfig.enabled = GeneralCompatConfig.creativeNoClip;
|
||||
OptimizedDragonRespawnConfig.optimizedRespawn = GeneralCompatConfig.optimizedDragonRespawn;
|
||||
}
|
||||
|
||||
private static void applyFakePlayerRules() {
|
||||
FakeplayerConfig.enable = FakePlayerCompatConfig.commandBot || FakePlayerCompatConfig.commandPlayer;
|
||||
FakeplayerConfig.canResident = FakePlayerCompatConfig.fakePlayerResident;
|
||||
FakeplayerConfig.canOpenInventory = FakePlayerCompatConfig.openFakePlayerInventory;
|
||||
FakeplayerConfig.tickType = FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer
|
||||
? ServerBot.TickType.NETWORK
|
||||
: ServerBot.TickType.ENTITY_LIST;
|
||||
}
|
||||
|
||||
private static void applyCounterRules() {
|
||||
WoolHopperCounterConfig.enabled = CounterCompatConfig.hopperCounters;
|
||||
WoolHopperCounterConfig.unlimitedSpeed = CounterCompatConfig.hopperCountersUnlimitedSpeed;
|
||||
}
|
||||
|
||||
private static List<String> sanitizeDefaultLoggers(List<String> configuredLoggers) {
|
||||
return configuredLoggers == null ? List.of() : List.copyOf(configuredLoggers);
|
||||
}
|
||||
|
||||
private static void registerProtocolRules() {
|
||||
CarpetServerProtocol.CarpetRules.clear();
|
||||
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "language", GeneralCompatConfig.language));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "amsUpdateSuppressionCrashFix", GeneralCompatConfig.amsUpdateSuppressionCrashFix));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "yeetUpdateSuppressionCrash", GeneralCompatConfig.yeetUpdateSuppressionCrash));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "dustTrapdoorReintroduced", GeneralCompatConfig.dustTrapdoorReintroduced));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "shulkerBoxCCEReintroduced", GeneralCompatConfig.shulkerBoxCCEReintroduced));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "instantBlockUpdaterReintroduced", GeneralCompatConfig.instantBlockUpdaterReintroduced));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandTick", GeneralCompatConfig.commandTick));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "creativeNoClip", GeneralCompatConfig.creativeNoClip));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedDragonRespawn", GeneralCompatConfig.optimizedDragonRespawn));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "antiSpamDisabled", GeneralCompatConfig.antiSpamDisabled));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "blockPlacementIgnoreEntity", GeneralCompatConfig.blockPlacementIgnoreEntity));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "creativeOpenContainerForcibly", GeneralCompatConfig.creativeOpenContainerForcibly));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "creativeOneHitKill", GeneralCompatConfig.creativeOneHitKill));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "observerNoDetection", GeneralCompatConfig.observerNoDetection));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "bambooModelNoOffset", GeneralCompatConfig.bambooModelNoOffset));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "creativeNoItemCooldown", GeneralCompatConfig.creativeNoItemCooldown));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "ctrlQCraftingFix", GeneralCompatConfig.ctrlQCraftingFix));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "carpetAlwaysSetDefault", GeneralCompatConfig.carpetAlwaysSetDefault));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "placementRotationFix", GeneralCompatConfig.placementRotationFix));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "tntDoNotUpdate", GeneralCompatConfig.tntDoNotUpdate));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "totallyNoBlockUpdate", GeneralCompatConfig.totallyNoBlockUpdate));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tiscmNetworkProtocol", GeneralCompatConfig.tiscmNetworkProtocol));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetorgaddition", "hopperNoItemCost", GeneralCompatConfig.hopperNoItemCost));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "explosionNoBlockDamage", GeneralCompatConfig.explosionNoBlockDamage));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedTNTHighPriority", GeneralCompatConfig.optimizedTNTHighPriority));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "tntPrimerMomentumRemoved", GeneralCompatConfig.tntPrimerMomentumRemoved));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntIgnoreRedstoneSignal", GeneralCompatConfig.tntIgnoreRedstoneSignal));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntDupingFix", GeneralCompatConfig.tntDupingFix));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "interactionUpdates", GeneralCompatConfig.interactionUpdates));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "xpNoCooldown", GeneralCompatConfig.xpNoCooldown));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "powerfulExpMending", GeneralCompatConfig.powerfulExpMending));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "clientSettingsLostOnRespawnFix", GeneralCompatConfig.clientSettingsLostOnRespawnFix));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "sensibleEnderman", GeneralCompatConfig.sensibleEnderman));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "entityInstantDeathRemoval", GeneralCompatConfig.entityInstantDeathRemoval));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "farmlandTrampledDisabled", GeneralCompatConfig.farmlandTrampledDisabled));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "shulkerGolem", GeneralCompatConfig.shulkerGolem));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "preventEndSpikeRespawn", GeneralCompatConfig.preventEndSpikeRespawn));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "yeetOutOfOrderChatKick", GeneralCompatConfig.yeetOutOfOrderChatKick));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "betterCraftableBoneBlock", GeneralCompatConfig.betterCraftableBoneBlock));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "betterCraftableDispenser", GeneralCompatConfig.betterCraftableDispenser));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "viewDistance", GeneralCompatConfig.viewDistance));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tickCommandPermission", GeneralCompatConfig.normalizedTickCommandPermission()));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tickFreezeCommandToggleable", GeneralCompatConfig.tickFreezeCommandToggleable));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "syncServerMsptMetricsData", GeneralCompatConfig.syncServerMsptMetricsData));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetorgaddition", "simpleInGameCalculator", GeneralCompatConfig.simpleInGameCalculator));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "microTiming", GeneralCompatConfig.microTiming));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "fastRedstoneDust", GeneralCompatConfig.fastRedstoneDust));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "lagFreeSpawning", GeneralCompatConfig.lagFreeSpawning));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedFastEntityMovement", GeneralCompatConfig.optimizedFastEntityMovement));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedHardHitBoxEntityCollision", GeneralCompatConfig.optimizedHardHitBoxEntityCollision));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntFuseDuration", GeneralCompatConfig.normalizedTntFuseDuration()));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "defaultLoggers", CarpetLoggerProtocol.serializeConfiguredDefaults(sanitizeDefaultLoggers(GeneralCompatConfig.defaultLoggers))));
|
||||
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "commandBot", FakePlayerCompatConfig.commandBot));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandPlayer", FakePlayerCompatConfig.commandPlayer));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerResident", FakePlayerCompatConfig.fakePlayerResident));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "openFakePlayerInventory", FakePlayerCompatConfig.openFakePlayerInventory));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "fakePlayerTicksLikeRealPlayer", FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerDefaultSurvivalMode", FakePlayerCompatConfig.fakePlayerDefaultSurvivalMode));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerInteractLikeClient", FakePlayerCompatConfig.fakePlayerInteractLikeClient));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoReplaceTool", FakePlayerCompatConfig.fakePlayerAutoReplaceTool));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoReplenishment", FakePlayerCompatConfig.fakePlayerAutoReplenishment));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerAutoReplenishmentFormShulkerBox", FakePlayerCompatConfig.fakePlayerAutoReplenishmentFormShulkerBox));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoFish", FakePlayerCompatConfig.fakePlayerAutoFish));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerReloadAction", FakePlayerCompatConfig.fakePlayerReloadAction));
|
||||
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "hopperCounters", CounterCompatConfig.hopperCounters));
|
||||
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", CounterCompatConfig.hopperCountersUnlimitedSpeed));
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
package fun.bm.lophine.carpet;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class InteractionUpdateCompatHelper {
|
||||
private static final ThreadLocal<Integer> SUPPRESSED_DEPTH = ThreadLocal.withInitial(() -> 0);
|
||||
|
||||
public static boolean shouldSkipUpdates() {
|
||||
return SUPPRESSED_DEPTH.get() > 0;
|
||||
}
|
||||
|
||||
public static void runWithSuppressedUpdates(Runnable action) {
|
||||
push();
|
||||
try {
|
||||
action.run();
|
||||
} finally {
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T supplyWithSuppressedUpdates(Supplier<T> action) {
|
||||
push();
|
||||
try {
|
||||
return action.get();
|
||||
} finally {
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
private static void push() {
|
||||
SUPPRESSED_DEPTH.set(SUPPRESSED_DEPTH.get() + 1);
|
||||
}
|
||||
|
||||
private static void pop() {
|
||||
int depth = SUPPRESSED_DEPTH.get();
|
||||
if (depth <= 1) {
|
||||
SUPPRESSED_DEPTH.remove();
|
||||
} else {
|
||||
SUPPRESSED_DEPTH.set(depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package fun.bm.lophine.carpet;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.EntitySpawnReason;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.FenceGateBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public final class LagFreeSpawningCompatHelper {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Map<ServerLevel, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
|
||||
|
||||
public static boolean hasNoCollision(ServerLevel world, AABB bb) {
|
||||
int minX = Mth.floor(bb.minX);
|
||||
int minY = Mth.floor(bb.minY);
|
||||
int minZ = Mth.floor(bb.minZ);
|
||||
int maxY = Mth.ceil(bb.maxY) - 1;
|
||||
BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
|
||||
|
||||
if (bb.getXsize() <= 1.0 && bb.getZsize() <= 1.0) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
blockPos.set(minX, y, minZ);
|
||||
VoxelShape shape = world.getBlockState(blockPos).getCollisionShape(world, blockPos);
|
||||
if (shape != Shapes.empty()) {
|
||||
return shape != Shapes.block() && world.noCollision(bb);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int maxX = Mth.ceil(bb.maxX) - 1;
|
||||
int maxZ = Mth.ceil(bb.maxZ) - 1;
|
||||
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
blockPos.set(x, y, z);
|
||||
VoxelShape shape = world.getBlockState(blockPos).getCollisionShape(world, blockPos);
|
||||
if (shape != Shapes.empty()) {
|
||||
return shape != Shapes.block() && world.noCollision(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int minBelow = minY - 1;
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
blockPos.set(x, minBelow, z);
|
||||
BlockState state = world.getBlockState(blockPos);
|
||||
Block block = state.getBlock();
|
||||
if (state.is(BlockTags.FENCES)
|
||||
|| state.is(BlockTags.WALLS)
|
||||
|| block instanceof FenceGateBlock && !state.getValue(FenceGateBlock.OPEN)) {
|
||||
if (x == minX || x == maxX || z == minZ || z == maxZ) {
|
||||
return world.noCollision(bb);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static double limitDistanceSq(MobCategory category, double distanceSq) {
|
||||
return distanceSq > 16384.0 && category != MobCategory.CREATURE ? 0.0 : distanceSq;
|
||||
}
|
||||
|
||||
public static @Nullable Mob getOrCreateMob(ServerLevel level, EntityType<?> entityType) {
|
||||
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level, key -> new HashMap<>());
|
||||
Mob mob = cache.get(entityType);
|
||||
if (mob != null && !mob.isRemoved()) {
|
||||
return mob;
|
||||
}
|
||||
|
||||
try {
|
||||
if (entityType.create(level, EntitySpawnReason.NATURAL) instanceof Mob created) {
|
||||
cache.put(entityType, created);
|
||||
return created;
|
||||
}
|
||||
LOGGER.warn("Can't precook non-mob entity type: {}", entityType);
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Failed to precook mob {}", entityType, exception);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void markSpawned(ServerLevel level, EntityType<?> entityType) {
|
||||
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level);
|
||||
if (cache != null) {
|
||||
cache.remove(entityType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fun.bm.lophine.carpet.config.modules;
|
||||
|
||||
//import fun.bm.lophine.carpet.CarpetCompatSync;
|
||||
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
@ConfigClassInfo(
|
||||
category = EnumConfigCategory.ROOT,
|
||||
name = "core",
|
||||
directory = {"carpet"}
|
||||
)
|
||||
public class CoreConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "enabled", comments = """
|
||||
Enable carpet features.
|
||||
If you want to use some function from Carpet modifier,
|
||||
you need to enable it.
|
||||
(some function is not managed by this option)
|
||||
|
||||
ONLY GENERAL DIRECTORY WAS CONTROLLED BY THIS OPTION.
|
||||
WARNING: IF YOU ENABLED IT, ORIGINAL CONFIG IN LOPHINE CONFIG WILL BE OVERWRITTEN.""")
|
||||
public static boolean enabled = false;
|
||||
|
||||
@Override
|
||||
public void beforeFinalLoad() {
|
||||
// CarpetCompatSync.apply();
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package fun.bm.lophine.carpet.config.modules;
|
||||
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
@ConfigClassInfo(
|
||||
category = EnumConfigCategory.ROOT,
|
||||
name = "hopper_counter",
|
||||
directory = {"carpet"},
|
||||
comments = """
|
||||
Hopper counter compatibility mapped onto Lophine's wool hopper counter implementation."""
|
||||
)
|
||||
public class CounterCompatConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "hopperCounters", comments = """
|
||||
Enable the existing wool hopper counter implementation.""")
|
||||
public static boolean hopperCounters = false;
|
||||
|
||||
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
|
||||
Remove the hopper transfer speed limit for counters.
|
||||
Only effective when hopperCounters is enabled.""")
|
||||
public static boolean hopperCountersUnlimitedSpeed = false;
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package fun.bm.lophine.carpet.config.modules;
|
||||
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
|
||||
@ConfigClassInfo(
|
||||
category = EnumConfigCategory.ROOT,
|
||||
name = "fakeplayer",
|
||||
directory = {"carpet"},
|
||||
comments = """
|
||||
Carpet fakeplayer compatibility mapped onto Lophine fakeplayers.
|
||||
commandPlayer is currently backed by Lophine's /bot command surface."""
|
||||
)
|
||||
public class FakePlayerCompatConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "commandBot", comments = """
|
||||
Enable Lophine's /bot command.""")
|
||||
public static boolean commandBot = false;
|
||||
|
||||
@ConfigInfo(name = "commandPlayer", comments = """
|
||||
Map Carpet's commandPlayer rule to the same fakeplayer command surface used by /bot.""")
|
||||
public static boolean commandPlayer = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerResident", comments = """
|
||||
Keep fakeplayers resident across unload and restart.""")
|
||||
public static boolean fakePlayerResident = false;
|
||||
|
||||
@ConfigInfo(name = "openFakePlayerInventory", comments = """
|
||||
Allow opening fakeplayer inventories.""")
|
||||
public static boolean openFakePlayerInventory = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerTicksLikeRealPlayer", comments = """
|
||||
Tick fakeplayers in the network phase to better match real player timing.""")
|
||||
public static boolean fakePlayerTicksLikeRealPlayer = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerDefaultSurvivalMode", comments = """
|
||||
Force newly created fakeplayers to start in survival instead of the server default gamemode.""")
|
||||
public static boolean fakePlayerDefaultSurvivalMode = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerInteractLikeClient", comments = """
|
||||
Make fakeplayer entity interaction follow client-side fallback behavior more closely.""")
|
||||
public static boolean fakePlayerInteractLikeClient = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerAutoReplaceTool", comments = """
|
||||
Toggle automatic tool replacement for fakeplayers.""")
|
||||
public static boolean fakePlayerAutoReplaceTool = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerAutoReplenishment", comments = """
|
||||
Toggle automatic stack replenishment for fakeplayers.""")
|
||||
public static boolean fakePlayerAutoReplenishment = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerAutoReplenishmentFormShulkerBox", comments = """
|
||||
Let fakeplayer replenishment pull matching items out of shulker boxes in the inventory.""")
|
||||
public static boolean fakePlayerAutoReplenishmentFormShulkerBox = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerAutoFish", comments = """
|
||||
Let fakeplayers holding a fishing rod automatically cast and reel it in.""")
|
||||
public static boolean fakePlayerAutoFish = false;
|
||||
|
||||
@ConfigInfo(name = "fakePlayerReloadAction", comments = """
|
||||
Persist queued fakeplayer actions across save and reload.""")
|
||||
public static boolean fakePlayerReloadAction = false;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user