Compare commits

..

82 Commits

Author SHA1 Message Date
Helvetica Volubi ed2f464914 fixup build 2026-06-25 18:12:18 +08:00
Helvetica Volubi 1cd09226f6 fixes #152 2026-06-25 17:49:55 +08:00
Helvetica Volubi 8cd8f4fbad Update Luminol 2026-06-25 17:48:52 +08:00
Bacteriawa e90c758a01 Lophine: add configs and update-suppression guards
Add Lophine-specific configuration support (global and carpet configs) and a temporary config transform step during init. Introduce config-controlled command registrations (function, scoreboard, trigger, tick) and enable tick-rate/command tweaks and an entity raytracing tracker flag. Fix datapack command save/listing behavior. Integrate Leaves update-suppression handling broadly: catch and convert update-suppression exceptions across packet handling, ticking, neighbor updates, block state updates and more; add configurable shulker CCE behavior and redstone upward-update compatibility. Provide an option to reintroduce an InstantNeighborUpdater (instant block updater) and other small compatibility/rebrand adjustments.
2026-06-23 01:35:57 +08:00
Helvetica Volubi e508462093 Update Luminol 2026-06-23 00:37:42 +08:00
dependabot[bot] b9c68a9b84 [ci skip]Bump actions/checkout from 6 to 7 (#153)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-20 16:36:49 +08:00
Helvetica Volubi 74d0b5ca5f Update Luminol & remove a unused config 2026-06-19 23:28:39 +08:00
Helvetica Volubi 4df4d07ae9 Merge the duplicate configuration items (#151)
* do not release & push repo before finished

* langs update

* updateSuppression config moved up

* redirect tick command option to carpet config system

* optimizedDragonRespawn

* diff in files

* counter rules transformed

* oops!

* some fakeplayer options moved up

* simplify

* creative no clip moved

* pre remove core module

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

* fix up transform

* fix up transform

* fix up

* fix up some problem in PR

* redirect forgotten moved config

* fix bugs in PR

* refix

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

* Fix NPE on Region Shutdown with bots

* simple fix up

* Revert "Fix NPE on Region Shutdown with bots"

This reverts commit b55c982cb9.

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

This reverts commit a721c27e96.

* fix: improve bot shutdown handling to prevent region crashes

---------

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

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

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

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

These changes allow disabling creeper/ghast block breaking and suppressing blaze/ghast-caused fire while preserving existing explosion event handling.
2026-06-03 13:22:25 +08:00
Bacteriawa 924ab75f1d Remove Carpet features patches and protocols
Delete Carpet integration: remove luminol and minecraft Carpet feature patch files (1todos/server/luminol-patches/features/0006-Carpet-features.patch and 1todos/server/minecraft-patches/features/0044-Carpet-features.patch) and remove related protocol implementations (1todos/server/src/lophine/protocol/CarpetLoggerProtocol.java and 1todos/server/src/lophine/protocol/tiscm/TISCMProtocol.java). These files contained the Carpet feature backport/compat patches and protocol helpers; removing them cleans up the obsolete Carpet-specific changes.
2026-06-03 13:22:25 +08:00
Bacteriawa 1b2f577e42 Add Carpet features, update Leaves patches
Register a new lophine_carpet config and add Carpet feature patches and protocol classes. Adds luminol and minecraft Carpet feature patches, plus CarpetLoggerProtocol and TISCMProtocol Java files. Updates many Leaves-related patch files (metadata and authors/dates) and applies Leaves behaviour changes across numerous block classes (onRemove handling, affectNeighborsAfterRemoval wiring, Containers.dropContentsOnDestroy, etc.) to preserve pre-1.21.1 behaviour and compatibility. These changes enable Carpet integration and ensure Leaves patches are consistently applied across the codebase.
2026-06-03 13:22:24 +08:00
Helvetica Volubi 76c504e86f add new option for push repo (#148)
* ci test push repo - false

* ci test push repo - true

* ci test push repo - auto

* set to correct value
2026-06-03 01:55:40 +08:00
Helvetica Volubi 7ada14e6b6 Update Luminol 2026-06-03 00:56:30 +08:00
Helvetica Volubi 24965b48c5 old block behavior re-patched 2026-06-03 00:33:11 +08:00
Bacteriawa 5dab6a557b Add redstone & crash-fix configs; fix exception
Add RedStoneConfig (EXPERIMENT) with toggles for redstone update behaviors, CCE usage, instant block updater, and old block removal; add UpdateSuppressionCrashFixConfig (FIXES) to enable crash prevention. Fix UpdateSuppressionException: provideLevel and provideBlock now assign their fields only when those fields are currently null, ensuring the first-provided context is preserved and preventing unintended overwrites.
2026-06-02 22:59:40 +08:00
Bacteriawa e27300d2c2 Add Leaves update-suppression & redstone patches
Flip release flag to 0 and add multiple Leaves-related minecraft patches. These patches add broad UpdateSuppressionException handling (providing player/level/block context and consuming exceptions) across packet processing, ticking, entity events, chunk updates and redstone logic to avoid crashes and lost drops. Also add CCE-safe redstone handling, an opt-in redstone "ignore upwards" update, instant block updater selection, revert TrapDoorBlock Paper changes, preserve item drops when breaking blocks, and avoid resetting placed blocks on exception / suppressing block-entity crashes. Patches rely on config flags (e.g. UpdateSuppressionCrashFixConfig and RedStoneConfig) and introduce new patch files under lophine-server/minecraft-patches/features.
2026-06-02 20:56:23 +08:00
Helvetica Volubi cd665f0168 [ci skip] update clip 2026-05-26 22:40:41 +08:00
Helvetica Volubi aa07ef21ca Update Luminol 2026-05-26 01:25:35 +08:00
Helvetica Volubi d50ad73a17 global entities counter applied 2026-05-21 16:46:53 +08:00
Helvetica Volubi 0d794003bc Update Luminol 2026-05-21 14:45:32 +08:00
Helvetica Volubi 3856196543 Start Pre-release 26.1.2
some patches still not applied, need further update
2026-05-17 05:37:52 +08:00
Helvetica Volubi eff43b61ff fake player patches applied 2026-05-17 04:24:05 +08:00
Helvetica Volubi 06514362b8 protocols update
patches 28/44
2026-05-17 03:29:22 +08:00
Helvetica Volubi 5b94c79f39 patches 22/44 2026-05-17 02:46:52 +08:00
Helvetica Volubi 24a315a368 fix up ci 2026-05-11 11:30:05 +08:00
Helvetica Volubi 3d54e47c5e more patches - stage 16/44 2026-05-11 11:12:58 +08:00
Helvetica Volubi 6aadb1ca19 update Luminol 2026-05-11 10:27:28 +08:00
Helvetica Volubi 0a4a6baf70 update Luminol 2026-05-07 14:36:44 +08:00
Helvetica Volubi ee36fab64c apply patch: Leaves - Item overstack util 2026-05-04 22:44:14 +08:00
Helvetica Volubi e85db692f3 Update Luminol 2026-05-04 17:04:01 +08:00
Helvetica Volubi 9635e516dd more patches - stage 12/44 2026-05-04 00:57:49 +08:00
Helvetica Volubi d7e1b3a6bb more patches - stage 8/44 2026-05-04 00:20:54 +08:00
Helvetica Volubi 0fc9a1426d apply more patches 2026-05-03 16:45:10 +08:00
Helvetica Volubi 017e49da8a apply some patches 2026-05-03 00:30:08 +08:00
M2ke4U 42d870e32b Updated upstream & Ported some leaves patches & Fixed issues in gitignore
Signed-off-by: MrHua269 <mrhua269@gmail.com>
2026-05-02 23:09:13 +08:00
Helvetica Volubi 54ff033ef6 fix: fix up ci 2026-05-02 01:46:03 +08:00
Helvetica Volubi 9761fde77d baseline of 26.1.2
WARNING: no patch merged, we will start merge later

there are to many update between 1.21.11 and 26.1.2, so we need more time to build a base version which can stable to use
2026-05-02 00:46:03 +08:00
Helvetica Volubi e0d42cb1d3 Update Luminol 2026-05-01 23:12:36 +08:00
xiaoyueyoqwq 559b2e089a Fix Syncmatica modifier cleanup (#141)
Co-authored-by: xiaoyueyoqwq <xiaoyueyoqwq@users.noreply.github.com>
2026-05-01 23:07:35 +08:00
Helvetica Volubi a07649d14d [ci skip]update code from Leaves to fix some bug 2026-05-01 23:06:47 +08:00
Helvetica Volubi 6aa709cf75 [ci skip] fixup ci 2026-04-22 18:30:09 +08:00
Helvetica Volubi 6a452799cc feat: add full blocking load option for localized language support 2026-04-22 13:26:54 +08:00
Helvetica Volubi e17a3f2033 perf: some perform update && update Gradle wrapper to version 9.4.1 2026-04-22 01:40:07 +08:00
Helvetica Volubi 74ac0bccf5 fix: fix some function is not covered by core config 2026-04-14 00:41:54 +08:00
xiaoxijun f65b7f176b Carpet features (#134)
* Carpet features

* refactor(config): move up config

* refactor file

diff in file system

* Update Luminol

* move up - stage 1

* Revert "Update Luminol"

This reverts commit 6f02993bfe.

* move up - stage 2

* new carpet features

* upload docs

* stage - pre update

* [ci skip]Update Luminol

only update for dev branch, so skip ci

* remove blank

* feat:add carpet core config & move some function to config load stage

* remove some unused value & logic

* fix up

* Update Luminol

* fix up

* remove imports update

* add warning to carpet system if it is enabled

* Update Luminol

* use new function to sync config

* oops!

* Update Luminol

* fix up a bug

* refactor

* Update Luminol

* move up directory

* Update Luminol

* oops!

* refactor need

* feat: add CoreConfig to enable general rules in CarpetCompatSync

* modify some default value

* fix: enhance HUD logger subscriptions and improve player data handling

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com>
2026-04-13 19:45:35 +08:00
Helvetica Volubi 97a17dbf78 fix: update Luminol plugin versions in build configuration 2026-04-13 18:35:25 +08:00
Bacteriawa c5194eeb8f Update Luminol 2026-04-11 03:40:59 +08:00
Helvetica Volubi 58c5573421 fix: fix some crash problem 2026-04-08 09:49:45 +08:00
Helvetica Volubi 1907a41329 perf: some perform update for global entities counter 2026-04-08 09:15:55 +08:00
Helvetica Volubi 21cce73216 fix GlobalEntitiesCounter again 2026-04-07 20:25:57 +08:00
Helvetica Volubi 163a9902cc fix: fix mob despawn when player is away from all the player 2026-04-02 18:38:19 +08:00
Helvetica Volubi ba1216d4d3 Update Luminol 2026-03-30 00:08:27 +08:00
dependabot[bot] beb5cbeb52 [ci skip]Bump gradle/actions from 5 to 6 (#135)
Bumps [gradle/actions](https://github.com/gradle/actions) from 5 to 6.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/v5...v6)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-28 18:41:16 +08:00
Helvetica Volubi 5cc4371833 Update Luminol 2026-03-26 08:50:42 +08:00
Helvetica Volubi 35f1e58d4d [ci skip]Update Luminol
only update for dev branch, so skip ci
2026-03-22 15:14:15 +08:00
Helvetica Volubi 690d7c2785 Update Luminol 2026-03-21 21:56:12 +08:00
Helvetica Volubi 115c9f8ee8 fix: try to fix a bug in syncmatica protocol 2026-03-19 19:00:17 +08:00
Helvetica Volubi faa3529943 feat: split timeout options to config file 2026-03-19 18:39:37 +08:00
Helvetica Volubi 3c3a2a6ff4 [ci skip] fixup 2026-03-16 18:09:49 +08:00
Helvetica Volubi 25776c7200 Update Luminol
我去,这个怎么没提交上
2026-03-16 16:39:26 +08:00
Helvetica Volubi 74e9d146e3 Update Luminol & adapt auto update system 2026-03-16 16:08:58 +08:00
Helvetica Volubi a8b2972e0e [ci skip] fix up a config transform flag 2026-03-14 01:38:42 +08:00
xiaoxijun ed3063a477 [ci skip]Update gradle.properties 2026-03-10 23:40:16 +08:00
Helvetica Volubi 85d2fa3372 feat: add Leaves' Creative Fly No Clip feature
fix #16
2026-03-09 00:13:34 +08:00
Helvetica Volubi b22e9e588b Update Luminol 2026-03-08 00:20:08 +08:00
Helvetica Volubi 90b751da5a Update Luminol 2026-03-03 20:55:18 +08:00
dependabot[bot] 7efeb48a7e [ci skip]Bump actions/upload-artifact from 6 to 7 (#133)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-28 16:29:34 +08:00
153 changed files with 7345 additions and 3126 deletions
+14 -11
View File
@@ -10,11 +10,11 @@ on:
workflow_dispatch:
inputs:
force-release:
description: "Force disable release if you enter 2, force release if you enter 1, default release if not released else skip release"
description: "Force disable release if you enter false, force release if you enter true, default release if not released else skip release"
required: false
default: ""
force-push:
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"
description: "Force disable push to repo if you enter false, force push to repo if you enter true, 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@v6
uses: actions/checkout@v7
- 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@v6
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,12 @@ 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'
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"
@@ -96,7 +99,7 @@ jobs:
fi
- name: Publish To 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'
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_push_repo == 'true' && !( inputs.force-push == 'false' )) || inputs.force-push == 'true'
continue-on-error: true
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
env:
@@ -104,7 +107,7 @@ jobs:
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
- name: Create Release - Pre Process
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'
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == 'false')) || inputs.force-release == 'true'
run: |
if [ "${{ inputs.comments }}" == "" ]; then
echo "No comments provided"
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
+1 -1
View File
@@ -8,7 +8,7 @@ build
/lophine-server/build.gradle.kts
/lophine-api/build.gradle.kts
/lophine-server/src/minecraft
/luminol-server/src/minecraft
/paper-server
/paper-api
/paper-api-generator
+1 -1
View File
@@ -45,7 +45,7 @@ git clone https://github.com/LuminolMC/Lophine.git
cd Lophine
# 应用补丁并构建 Paperclip JAR
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
./gradlew applyAllPatches && ./gradlew createPaperclipJar
```
构建完成后,您可以在 `lophine-server/build/libs` 目录中找到生成的 JAR 文件。
+1 -1
View File
@@ -45,7 +45,7 @@ git clone https://github.com/LuminolMC/Lophine.git
cd Lophine
# Apply patches and build Paperclip JAR
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
./gradlew applyAllPatches && ./gradlew createPaperclipJar
```
After building, you can find the generated JAR file in the `lophine-server/build/libs` directory.
+7 -4
View File
@@ -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 {
}
}
}
}
}
+89
View File
@@ -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` 动作 |
+10 -8
View File
@@ -1,13 +1,15 @@
group=fun.bm.lophine
version=1.21.11-R0.1-SNAPSHOT
mcVersion=1.21.11
# This is the current API version for use in (paper-)plugin.yml files
# During snapshot cycles this should be the anticipated version of the release target
apiVersion=1.21.11
release=2
# 0 for skip release, 1 for pre-release, 2 for release
mcVersion=26.1.2
apiVersion=26.1.2
channel=STABLE
clipVersion=3.0.18
weightVersion=2.0.15
# true for release, false for skip release, pre for pre-release
release=true
# true for push to repo, false for skip push repo, auto for detect by release value
pushRepo=auto
luminolRef=78a3b89f5850f71ddb5b1d1adeccda47f5762a1b
luminolRef=2a3c21971bf030511823915c8b8d537f6d5963eb
org.gradle.configuration-cache=true
org.gradle.caching=true
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
@@ -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);
}
@@ -8,13 +8,13 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index b9d34c0b80a5d0c26f43e4959c3a8256a854585a..850f65d764030b09d469e33a69409204503d9ca1 100644
index 8e96326c55510642df01ef15e1a3edb1e81176cb..592a3c59bf5edbc65c7c0472e2382593b7b22086 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -3039,4 +3039,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
+ /**
@@ -28,10 +28,10 @@ index b9d34c0b80a5d0c26f43e4959c3a8256a854585a..850f65d764030b09d469e33a69409204
+ // Leaves end - Bot API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 1dc5d8c96786950fc98cada5bad981c0c716b154..cb8c4e09511f99558eb5af26c08c5cb1f936780d 100644
index 473b0e02c003d5317ef798c320e5c845124f4e12..978e015e91408503b4ec84ec5b3c5193255ba7db 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2791,4 +2791,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
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 850f65d764030b09d469e33a69409204503d9ca1..78b947352aa32ae0c59101459f420bf8e3497707 100644
index 592a3c59bf5edbc65c7c0472e2382593b7b22086..838ad878528267b57b69d2938aee0eb6326948eb 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -3050,4 +3050,10 @@ public final class Bukkit {
@@ -3059,4 +3059,10 @@ public final class Bukkit {
return server.getBotManager();
}
// Leaves end - Bot API
@@ -23,10 +23,10 @@ index 850f65d764030b09d469e33a69409204503d9ca1..78b947352aa32ae0c59101459f420bf8
+ // Leaves end - Photographer API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index cb8c4e09511f99558eb5af26c08c5cb1f936780d..b770b6f990d46f5325554f5d73c6a2a6ed361158 100644
index 978e015e91408503b4ec84ec5b3c5193255ba7db..d054926f6082bba7d0b59e610e5d725ff5f9ffa4 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2800,4 +2800,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -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
+18 -27
View File
@@ -1,6 +1,6 @@
--- a/luminol-server/build.gradle.kts
+++ b/luminol-server/build.gradle.kts
@@ -48,7 +_,23 @@
@@ -50,7 +_,23 @@
}
}
@@ -24,8 +24,8 @@
+ activeFork = lophine
spigot {
@@ -139,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,40 +42,31 @@
}
}
val log4jPlugins = sourceSets.create("log4jPlugins") {
@@ -172,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("io.netty:netty-all:4.2.9.Final") // used for io_uring
implementation("com.electronwill.night-config:toml:3.8.3") // Night config
@@ -273,14 +_,14 @@
implementation("net.objecthunter:exp4j:0.4.8")
implementation("com.electronwill.night-config:toml:3.9.0") // Night config
@@ -234,14 +_,14 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
"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,
@@ -432,7 +_,7 @@
}
fill {
- project("luminol")
+ project("lophine")
versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") })
version(paperweight.minecraftVersion)
@@ -5,14 +5,14 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 0bebc2cc87fb9c1c526e4de4f3bc157552307a72..cb1657939b86c039fcfe6403d3f202c2c5879e88 100644
index a2f5a99ee45a0810fd338ccf6f71df3a077ca62b..05e1aa84586284ac0389e7023f975bfb08438535 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -23,6 +23,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
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
preLoad();
}
@@ -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,40 +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 ad2ba680bedb2336de24146676e70a1f64fd9c5a..f81581782bf684bbcf4719e9b268efa3c6385325 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
@@ -13,6 +13,7 @@ public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "enable_data_command")
@HotReloadUnsupported
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.
@@ -20,6 +21,9 @@ public class CommandConfig implements IConfigModule {
DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING!!!
""")
public static boolean commandBlock = false;
+ @TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint bar"})
+ @TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
+ @TransformedConfig(name = "waypoint_command_enabled", directory = {"experiment", "command"})
@ConfigInfo(name = "enable_waypoints_and_waypoint_command", comments = """
Enable waypoint and waypoint command.
WARN: Still under testing
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java
index ce190737de22438d5de86b0ee0e8158954fdca18..0a175e87f3cb5b23480abefd70ee2e84e876b0d4 100644
--- a/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java
@@ -11,6 +11,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
"has negative impacts on security"
)
public class PaperPacketLimiterConfig implements IConfigModule {
+ @TransformedConfig(name = "unlimit-packet", directory = {"misc", "network"}, originInstance = "lophine")
@TransformedConfig(name = "force_disable", directory = {"optimizations", "force_disable_packet_limiter_of_paper"})
@ConfigInfo(name = "force_disable")
public static boolean forceDisable = false;
@@ -3,74 +3,188 @@ 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 112dc08eb62c4c50fb4859f51a366cedf027ca00..b5f661fd20b382725ad117c56ce2c94ded32b1b7 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,6 +17,7 @@
@@ -17,10 +17,98 @@
package org.leavesmc.leaves.util;
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.ItemEnchantments;
import net.minecraft.core.component.DataComponents;
@@ -135,9 +136,9 @@ public class ItemOverstackUtils {
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.entity.item.ItemEntity;
+import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.item.component.ItemContainerContents;
+import net.minecraft.world.level.block.ShulkerBoxBlock;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
private static class ShulkerBox implements ItemUtil {
public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
- /*if (LeavesConfig.modify.shulkerBox.sameNbtStackable) {
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
return Objects.equals(stack1.getComponents(), stack2.getComponents());
- }*/ // Luminol
// Only used part of the original code was copied
public class ItemOverstackUtils {
+
+ private static final List<ItemUtil> overstackUtils = List.of(
+ new ShulkerBox()
+ );
+
+ public static int getItemStackMaxCount(ItemStack stack) {
+ int size;
+ for (ItemUtil util : overstackUtils) {
+ if (util.isEnabled() && (size = util.getMaxServerStackCount(stack)) != -1) {
+ return size;
+ }
return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
}
@@ -147,16 +148,15 @@ public class ItemOverstackUtils {
@Override
public boolean isEnabled() {
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes > 1; // Luminol
- return false; // Luminol
+ }
+ return stack.getMaxStackSize();
+ }
+
+ public static int getNetworkMaxCount(ItemStack stack) {
+ int size;
+ for (ItemUtil util : overstackUtils) {
+ if (util.isEnabled() && (size = util.getMaxClientStackCount(stack)) != -1) {
+ return size;
+ }
+ }
+ return stack.getMaxStackSize();
+ }
+
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
+ for (ItemUtil util : overstackUtils) {
+ if (util.isEnabled() && util.tryStackItems(self, other)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean hasOverstackingItem() {
+ for (ItemUtil util : overstackUtils) {
+ if (util.isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static int getItemStackMaxCountReal(ItemStack stack) {
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
+ return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize());
+ }
+
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
+ int modifiedMaxStackSize = getNetworkMaxCount(itemStack);
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
+ nbt.putInt("Leaves.RealStackSize", realMaxStackSize);
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
+ }
+ return itemStack;
+ }
+
+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) {
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
+ if (itemStack.getMaxStackSize() != realMaxStackSize) {
+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize);
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
+ nbt.remove("Leaves.RealStackSize");
+ if (nbt.isEmpty()) {
+ itemStack.remove(DataComponents.CUSTOM_DATA);
+ } else {
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
+ }
+ }
+ return itemStack;
+ }
+
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);
}
+
+ public static boolean isStackable(ItemStack itemStack) {
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
+ }
+
+ private interface ItemUtil {
+ boolean isEnabled();
+
+ boolean tryStackItems(ItemEntity self, ItemEntity other);
+
+ // number -> modified count, -1 -> I don't care
+ int getMaxServerStackCount(ItemStack stack);
+
+ // number -> modified count, -1 -> I don't care
+ default int getMaxClientStackCount(ItemStack stack) {
+ return getMaxServerStackCount(stack);
+ }
+ }
+
+ private static class ShulkerBox implements ItemUtil {
+ public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
+ return Objects.equals(stack1.getComponents(), stack2.getComponents());
+ }
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
+ }
+
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
+ // Leaves - Paper 26.1: ItemContainerContents#stream() removed, use nonEmptyItemCopyStream()
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).nonEmptyItemCopyStream().findAny().isEmpty();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return ContainerExpansionConfig.shulkerCount > 1;
}
@Override
public boolean tryStackItems(ItemEntity self, ItemEntity other) {
ItemStack selfStack = self.getItem();
if (!isEnabled() ||
- !(selfStack.getItem() instanceof net.minecraft.world.item.BlockItem blockItem) ||
- !(blockItem.getBlock() instanceof net.minecraft.world.level.block.ShulkerBoxBlock)
+ !(selfStack.getItem() instanceof BlockItem blockItem) ||
+ !(blockItem.getBlock() instanceof ShulkerBoxBlock)
) {
return false;
}
@@ -164,8 +164,8 @@ public class ItemOverstackUtils {
ItemStack otherStack = other.getItem();
if (selfStack.getItem() == otherStack.getItem()
&& shulkerBoxCheck(selfStack, otherStack)
- && selfStack.getCount() != /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/ 1) { // Luminol
- int amount = Math.min(otherStack.getCount(), /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/1 - selfStack.getCount()); // Luminol
+ }
+
+ @Override
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
+ ItemStack selfStack = self.getItem();
+ if (!(selfStack.getItem() instanceof BlockItem blockItem) || !(blockItem.getBlock() instanceof ShulkerBoxBlock)) {
+ return false;
+ }
+
+ ItemStack otherStack = other.getItem();
+ if (selfStack.getItem() == otherStack.getItem()
+ && shulkerBoxCheck(selfStack, otherStack)
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
selfStack.grow(amount);
self.setItem(selfStack);
@@ -187,9 +187,8 @@ public class ItemOverstackUtils {
@Override
public int getMaxServerStackCount(ItemStack stack) {
if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
- bi.getBlock() instanceof ShulkerBoxBlock && (/*LeavesConfig.modify.shulkerBox.sameNbtStackable ||*/ shulkerBoxNoItem(stack))) { // Luminol
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes; // Luminol
- return 1; // Luminol
+
+ selfStack.grow(amount);
+ self.setItem(selfStack);
+
+ self.pickupDelay = Math.max(other.pickupDelay, self.pickupDelay);
+ self.age = Math.min(other.getAge(), self.age);
+
+ otherStack.shrink(amount);
+ if (otherStack.isEmpty()) {
+ other.discard();
+ } else {
+ other.setItem(otherStack);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getMaxServerStackCount(ItemStack stack) {
+ if (stack.getItem() instanceof BlockItem bi &&
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
+ return ContainerExpansionConfig.shulkerCount;
}
return -1;
}
+ }
+ return -1;
+ }
+ }
}
@@ -3,15 +3,12 @@ From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 18 Feb 2026 00:15:08 +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/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
index 14cf379decfd46c4719bc192a1467bbbd6835417..20970844de2e64ca213384e53003e80020165770 100644
index 389a31b14912a2dfc8e8b20c104505d211d7f8ad..04b9e3a432181c9698e1a4c147b420c230b66a36 100644
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
@@ -38,6 +38,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
@@ -55,6 +55,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
return;
}
@@ -24,16 +21,36 @@ index 14cf379decfd46c4719bc192a1467bbbd6835417..20970844de2e64ca213384e53003e800
this.waypoints.add(waypoint);
for (ServerPlayer toCreateFor : this.trackingPlayers) {
@@ -91,6 +97,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
public void addPlayer(ServerPlayer player) {
this.trackingPlayers.add(player);
@@ -111,6 +117,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
scheduleIfOffTarget(player, () -> {
this.trackingPlayers.add(player);
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
+
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
this.createConnection(player, waypointTransmitter);
for (WaypointTransmitter transmitter : this.waypoints) {
this.createConnection(player, transmitter);
}
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
index 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab5822601939 100644
--- 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") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: 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 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c 100644
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
@@ -12,6 +12,7 @@ public class ServerFeatureManager implements FeatureManager {
private ServerFeatureManager() {
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 3 Jun 2026 13:49:39 +0800
Subject: [PATCH] Update suppression event
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
index 0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c..c3db6c5281728fa1a2b4d84f9ebff9fcfd696698 100644
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
@@ -13,6 +13,7 @@ public class ServerFeatureManager implements FeatureManager {
private ServerFeatureManager() {
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
+ availableFeatures.add(UPDATE_SUPPRESSION_EVENT); // Lophine - update suppression event support
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
availableFeatures.add(MIXIN);
}
@@ -0,0 +1,26 @@
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 05e1aa84586284ac0389e7023f975bfb08438535..5a8c94337e42584ddaf25ef289327777e7ac675e 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -25,6 +25,15 @@ public class ConfigManager {
public static void initConfigs() {
registerConfig("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
registerConfig("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
+ // Lophine start - add carpet config
+ registerConfig("lophine_carpet", ConfigsInstance.of(
+ new java.io.File("lophine_config"),
+ "lophine_carpet",
+ "lophine_carpet_config.toml",
+ "lophinecarpetconfig",
+ "fun.bm.lophine.carpet.config.modules"
+ ));
+ // Lophine end - add carpet config
preLoad();
}
@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 5 Jun 2026 16:10:25 +0800
Subject: [PATCH] Carpet Features Compatible
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
index f079a1cd99d648dc7ca97fb65406b7a42ad5a74e..30f78cbae7aea3e9fcee6d97f229ddf8e8344299 100644
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
@@ -23,9 +23,4 @@ public class CommandConfig implements IConfigModule {
""")
@HotReloadUnsupported
public static boolean waypointsAndWaypointCommand = false;
- @ConfigInfo(name = "enable_tick_command", comments = """
- Only freeze/unfreeze/step/query command is allowed if you enabled it.
- WARN: This should disabled in production environment!
- """)
- public static boolean tick = false;
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
deleted file mode 100644
index f791feed92abd750ac10775c05150f122ecbe886..0000000000000000000000000000000000000000
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package me.earthme.luminol.config.modules.optimizations;
-
-import me.earthme.luminol.config.IConfigModule;
-import me.earthme.luminol.config.flags.ConfigClassInfo;
-import me.earthme.luminol.config.flags.ConfigInfo;
-import me.earthme.luminol.enums.EnumConfigCategory;
-
-@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "end_dragon")
-public class OptimizedDragonRespawnConfig implements IConfigModule {
- @ConfigInfo(name = "optimized_dragon_respawn")
- public static boolean optimizedRespawn = false;
-}
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 15 Jun 2026 01:33:32 +0800
Subject: [PATCH] TEMP: Temporarily transform config between different config
system
Should be removed in Minecraft 26.2 Update
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 5a8c94337e42584ddaf25ef289327777e7ac675e..b652525f243c23e09c4e13f67617e99a3ce0db04 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -64,6 +64,12 @@ public class ConfigManager {
CompletableFuture.allOf(futures).join();
CommandRegister.register(); // register command after config loaded to enable some command didn't depend on config files
initialized = true;
+
+ // Lophine start - temporarily transform configs
+ reApplyStagedConfigs();
+ saveConfigs();
+ configfiles.values().forEach((config) -> config.reload(true, false));
+ // Lophine end - temporarily transform configs
}
public static void registerRunnableBeforeFinalLoad(Runnable runnable) {
@@ -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 f41c70c6cb2e9fae43bad9dd66546417fe38f14a..0bb0877011cac3184b881bfa35f10ef83d7341de 100644
index 143ad4e342b184aa02b6fbbe81508e244eebc7a2..89be42b8519522398920eb424c894fd2ab8c9666 100644
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -151,6 +151,8 @@ public class Main {
@@ -155,6 +155,8 @@ public class Main {
return;
}
@@ -39,10 +39,10 @@ index f41c70c6cb2e9fae43bad9dd66546417fe38f14a..0bb0877011cac3184b881bfa35f10ef8
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 4abfcaae4fe024296961987704e2a11a03ee518b..5fbcb5eac1d5449247da77b6120edbe2f2dd1d58 100644
index 3707b03b6d7ebdf47a38f4feff5b738eb41f38e1..1bc1e9a77dca7acfe5f989f6439f185d0d2e20a6 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -262,6 +262,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
@@ -5,16 +5,16 @@ Subject: [PATCH] Fix datapack command save function
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d7d22806c010636d8c1471f0fd1d64ef54e92c97..8d96d2130cf3383427047fee97fa49155164e337 100644
index 28384f9ebfcdbfbd07fc7fe3c929786eb9e2ccd3..d1cc2f956213add0e04d51db7b9da7076b521d8b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2431,6 +2431,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
@@ -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> selectedIds) {
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
+ 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()
+ );
@@ -22,11 +22,11 @@ index d7d22806c010636d8c1471f0fd1d64ef54e92c97..8d96d2130cf3383427047fee97fa4915
+ }
+ // 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(
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 bb36fa4559cdfe82079af1c39516239119ff06f4..8c530eef0e416d8b96f190ada358d77d34dbc8ac 100644
index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..991e0362e96488b64d994f1bdfb8ed5d66f98666 100644
--- a/net/minecraft/server/commands/DataPackCommand.java
+++ b/net/minecraft/server/commands/DataPackCommand.java
@@ -98,7 +98,7 @@ public class DataPackCommand {
@@ -34,55 +34,46 @@ index bb36fa4559cdfe82079af1c39516239119ff06f4..8c530eef0e416d8b96f190ada358d77d
Commands.literal("datapack")
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
- /*.then( // Luminol - Add back read-only datapack command
+ .then(
+ .then( // Lophine - Fix datapack command save function
Commands.literal("enable")
.then(
Commands.argument("name", StringArgumentType.string())
@@ -160,11 +160,11 @@ public class DataPackCommand {
@@ -145,11 +145,11 @@ public class DataPackCommand {
.suggests(SELECTED_PACKS)
.executes(commandContext -> disablePack(commandContext.getSource(), getPack(commandContext, "name", false)))
.executes(c -> disablePack(c.getSource(), getPack(c, "name", false)))
)
- )*/ // Luminol - Add back read-only datapack command
+ )
.then(
Commands.literal("list")
.executes(commandContext -> listPacks(commandContext.getSource()))
- // .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource()))) // Luminol - Add back read-only datapack command
+ .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource())))
.then(Commands.literal("enabled").executes(commandContext -> listEnabledPacks(commandContext.getSource())))
.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(
@@ -252,7 +252,7 @@ public class DataPackCommand {
@@ -235,7 +235,7 @@ public class DataPackCommand {
}
private static int listPacks(CommandSourceStack source) {
private static int listPacks(final CommandSourceStack source) {
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
+ return listEnabledPacks(source) + listAvailablePacks(source);
+ return listEnabledPacks(source) + listAvailablePacks(source); // Lophine - Fix datapack command save function
}
private static int listAvailablePacks(CommandSourceStack source) {
@@ -280,7 +280,7 @@ public class DataPackCommand {
private static int listEnabledPacks(CommandSourceStack source) {
PackRepository packRepository = source.getServer().getPackRepository();
- // packRepository.reload(); // Luminol - Add back read-only datapack command
+ packRepository.reload();
Collection<? extends Pack> selectedPacks = packRepository.getSelectedPacks();
if (selectedPacks.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.datapack.list.enabled.none"), false);
private static int listAvailablePacks(final CommandSourceStack source) {
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
index fcca0babb4e7929cc168fc8b9ad47619e6feb1a5..bac5f4e023f8b73eebea0f31fd253e04c8809918 100644
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(Collection<String> selectedIds, CommandSourceStack source) {
public static void reloadPacks(final Collection<String> selectedPacks, final CommandSourceStack source) {
+ // Lophine start - region thread skip reload // TODO - add reload support
+ source.getServer().saveDatapacks(selectedIds);
+ source.getServer().saveDatapacks(selectedPacks);
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
+ if (false) {
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
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;
@@ -91,4 +82,4 @@ index fcca0babb4e7929cc168fc8b9ad47619e6feb1a5..bac5f4e023f8b73eebea0f31fd253e04
+ // Lophine end - region thread skip reload // TODO - add reload support
}
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
private static Collection<String> discoverNewPacks(final PackRepository packRepository, final WorldData worldData, final Collection<String> currentPacks) {
@@ -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 2eb551390aa66d89988df9ca23cf0dd7ccfd6577..0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d 100644
index 63b81f30b8d813a7986ae72842fdc2d3097fa103..527c495bb4f6007aee760b99cc0e9aa589931f4b 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -963,6 +963,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 2eb551390aa66d89988df9ca23cf0dd7ccfd6577..0d322ef4aa3e70c9edbb9fa8ba368bef
// 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 0f6e1428cc71c370af45db3e2a4f47c66e5d8628..83612969b6058f444fc17e360cdcc4a8846f79aa 100644
index 1413286ddc63c5978e745eb26f6012230e4b1cd6..234124cc64e5175c20f9e9f0f482c9c677bca563 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -179,6 +179,7 @@ public abstract class Player extends Avatar implements ContainerUser {
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 0f6e1428cc71c370af45db3e2a4f47c66e5d8628..83612969b6058f444fc17e360cdcc4a8
// CraftBukkit start
public boolean fauxSleeping;
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
index 1fb3a34ea872dec73658fac59743e46ef8db5151..41ebe774edfe3c37afecda514a6eb7db978d5aa8 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 9749909b8253b432bb2f7fba2cd8ff17a8579b30..42df617d7b62af45bd56e9594689974f790f6c19 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,35 +90,35 @@ index 9749909b8253b432bb2f7fba2cd8ff17a8579b30..42df617d7b62af45bd56e9594689974f
+ }
+ // 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 383e8285d366c7f594b0b4ff55b367970c9b69e4..202a986762794da9440365953fcb950c6eefa774 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 dcec63c1c2634a3e83ee3cac26f6e51441c37f6d..e5cfbf41525b0d454bb83691354afb4513723571 100644
index 61e39a18c0fba22699750e5c0187d19a0433b9a2..98c48426fcbb4aeba479e87ab27b03e17b50d7f5 100644
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -59,7 +59,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");
@@ -135,9 +135,9 @@ index dcec63c1c2634a3e83ee3cac26f6e51441c37f6d..e5cfbf41525b0d454bb83691354afb45
+ // Purpur end - Barrels and enderchests 6 rows
+
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
@Override
protected void onOpen(Level level, BlockPos pos, BlockState state) {
@@ -111,7 +121,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 dcec63c1c2634a3e83ee3cac26f6e51441c37f6d..e5cfbf41525b0d454bb83691354afb45
}
@Override
@@ -132,7 +151,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
}
@@ -5,10 +5,10 @@ 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 bd344bbebc867f89061694edc0feeab9d679c90c..6d0bb9868e2c2ef516de7630442808c04ba47b39 100644
index e12927623e8de82a6105b0cb0e6b58a6c45cff7e..0b5f2060062a354bd6cafa8f53a5734dc83d062d 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -392,7 +392,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()) {
@@ -17,7 +17,7 @@ index bd344bbebc867f89061694edc0feeab9d679c90c..6d0bb9868e2c2ef516de7630442808c0
// 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 true;
@@ -411,7 +411,7 @@ public class ServerGamePacketListenerImpl
@@ -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) {
@@ -26,28 +26,28 @@ index bd344bbebc867f89061694edc0feeab9d679c90c..6d0bb9868e2c2ef516de7630442808c0
// 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 true;
@@ -662,7 +662,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 && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // 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.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(d7));
@@ -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));
}
@@ -1564,7 +1564,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 && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
if (event.getLogWarning()) {
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), d3, d4, d5);
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), xDist, yDist, zDist);
}
@@ -1643,7 +1643,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 && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
movedWrongly = true;
@@ -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 08e0dde0aa5ff94b72127abcd7da2a63d5701db8..e311502c156076842c5dcd91c70a94e414312100 100644
index fecab5bfbc35fbecef8c559369de70c198bfe1e7..338e0c7c09120c6e9617893dd074cbd5da40a093 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1445,6 +1445,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
killCredit.awardKillScore(this, damageSource);
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, EntityEvent.DEATH);
@@ -1468,6 +1475,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1487,6 +1494,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Leaves end - exp fix
@@ -48,24 +48,24 @@ index 08e0dde0aa5ff94b72127abcd7da2a63d5701db8..e311502c156076842c5dcd91c70a94e4
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 c67c29278ea63ab8b936d53bf654089f2dba2eef..88d532d11c29bd8cfe5b6b02847d960b07cf0a38 100644
index cd2fb9e2110d0dba1358daa283af767db3f4e80a..cc7b2ea7fda1326e3f9ed46373190a05f60c4d34 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1975,6 +1975,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
@@ -1985,6 +1992,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 c67c29278ea63ab8b936d53bf654089f2dba2eef..88d532d11c29bd8cfe5b6b02847d960b
+ 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 c67c29278ea63ab8b936d53bf654089f2dba2eef..88d532d11c29bd8cfe5b6b02847d960b
+ }
+ // 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
@@ -2612,6 +2631,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -2629,6 +2649,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
}
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable save-all command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 17108636a5728efe98a064001e00e3ca098b1f51..7748e9ac04fbd3f5259d92fc908d90889cba86c8 100644
index 11cacb26ce260373476dad764014ba1852477831..981f63b75584dbcb4bb0d5672e8c8bb140c52f9d 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -350,6 +350,8 @@ public final class RegionizedServer {
@@ -364,6 +364,8 @@ public final class RegionizedServer {
// tick player ping sample
this.tickPlayerSample();
@@ -31,10 +31,10 @@ index 02c004bc7f9a0203523ce4b27cd766d6bdc478c0..3d86e21198f2888422330b6f7c27712f
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 6cb0d4daf0f275b95d5ca09275e40ab32258eb39..48628174299f8f18170198df1834d6174bd1fafa 100644
index 89f61f5715942d2b521e04b9fdc8b1b379c0c957..2c2487e1c1c65438119a13bd705a9e44697955ed 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -294,7 +294,11 @@ public class Commands {
@@ -299,7 +299,11 @@ public class Commands {
PardonCommand.register(this.dispatcher);
PardonIpCommand.register(this.dispatcher);
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
@@ -48,13 +48,13 @@ index 6cb0d4daf0f275b95d5ca09275e40ab32258eb39..48628174299f8f18170198df1834d617
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4be383909addfebc0ca3b007d4ef2ec30ed445f7..fa60388376e9dafc5e1b71b6e78550bb6cd4009b 100644
index d1cc2f956213add0e04d51db7b9da7076b521d8b..82013a8f7cf07b6f0645ca6b51ee75fcb0a56298 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1656,6 +1656,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1683,6 +1683,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - region threading
public void tickServer(long startTime, long scheduledEnd, long targetBuffer,
io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
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);
@@ -64,20 +64,20 @@ index 4be383909addfebc0ca3b007d4ef2ec30ed445f7..fa60388376e9dafc5e1b71b6e78550bb
// 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 e37b71402179c73146ff67babc228ccfb996f8f4..cfdb60bd89d83282f2202a5585bac22a6002e138 100644
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(CommandSourceStack source, boolean flush) throws CommandSyntaxException {
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 flag = server.saveEverything(true, flush, true);
if (!flag) {
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);
@@ -5,17 +5,19 @@ Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 9c0c3835776bda3bab08f0abaffc89a72bba0bfc..b95d144dd479d339cc4b0f92cc4c3bade9af4927 100644
index 2c2487e1c1c65438119a13bd705a9e44697955ed..4e0428948d618b0a072679762dc3cb39d6e12c2f 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -215,7 +215,9 @@ public class Commands {
@@ -217,7 +217,11 @@ public class Commands {
FillCommand.register(this.dispatcher, context);
FillBiomeCommand.register(this.dispatcher, context);
ForceLoadCommand.register(this.dispatcher);
- //FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ // Lophine start - Add config to enable function command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.function) {
+ FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
+ }
+ // Lophine end - Add config to enable function command
GameModeCommand.register(this.dispatcher);
GameRuleCommand.register(this.dispatcher, context);
GiveCommand.register(this.dispatcher, context);
@@ -1,167 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add config to enable tick command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 7748e9ac04fbd3f5259d92fc908d90889cba86c8..80b5d151e0dd6fa44794187875b4b80519839d81 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -332,6 +332,11 @@ public final class RegionizedServer {
this.randomWalk();
*/
++this.tickCount;
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.tick();
+ }
+ // Luminol end - Add a config to enable tick command
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -357,6 +362,13 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.reduceSprintTicks();
+ MinecraftServer.tickRateManager.endTickWork();
+ }
+ // Luminol end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
@@ -492,7 +504,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final long tickCount) {
- if (world.tickTime) {
+ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
if (world.getGameRules().get(GameRules.ADVANCE_TIME)) {
world.setDayTime(world.levelData.getDayTime() + tickCount);
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 0f4e8ee9438135e24e0f61a1390c59573b9e9c3f..65699d2ad66c686a8b7d1b951787ddd766800a94 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Luminol - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Luminol - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -448,8 +448,23 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Luminol start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = MinecraftServer.tickRateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Luminol end - Add tick command support
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
@@ -498,6 +513,11 @@ public final class TickRegionScheduler {
try {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.endTickWork();
+ }
+ // Luminol end - Add a config to enable tick command
} catch (final Throwable thr) {
this.scheduler.regionFailed(this, false, thr);
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index bd8d98aa813b575e83138e79726bd3143268913c..65f200381f486146ce8d893378f0591a82f6076b 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -262,7 +262,11 @@ public class Commands {
TeleportCommand.register(this.dispatcher);
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
- //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Luminol start - Add a config to enable tick command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Luminol end - Add a config to enable tick command
TimeCommand.register(this.dispatcher);
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 76098a4f44f8d82bebf832fa5e240adf25fbe80a..644c49730fc08a7c680f8114136db00ee8f81378 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -270,7 +270,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private @Nullable String serverId;
public MinecraftServer.ReloadableResources resources;
private final StructureTemplateManager structureTemplateManager;
- private final ServerTickRateManager tickRateManager;
+ public static ServerTickRateManager tickRateManager; // Luminol - Add tick command support
private final ServerDebugSubscribers debugSubscribers = new ServerDebugSubscribers(this);
protected WorldData worldData;
private LevelData.RespawnData effectiveRespawnData = LevelData.RespawnData.DEFAULT;
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index 4257c47d33e3773fac766817138cc21c55d9ab76..95f6b1cbd5e33151c326689bc72292ff38a48803 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -106,7 +106,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -114,6 +114,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Luminol start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Luminol end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index 14c46d585fc9bfbf9a57340508ea2e5076ac39d6..99096896a4512eed579b234e7fa0c6e9c3e8c246 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Luminol - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 097e5b6a14fd148c93ca3894295a4a6b1e9aa870..bd8d98aa813b575e83138e79726bd3143268913c 100644
index 4e0428948d618b0a072679762dc3cb39d6e12c2f..87ffca5ff0c2775cb85a6058c9be66e00c94f01f 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -241,7 +241,11 @@ public class Commands {
@@ -246,7 +246,11 @@ public class Commands {
RotateCommand.register(this.dispatcher);
SayCommand.register(this.dispatcher);
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
@@ -17,7 +17,7 @@ index 097e5b6a14fd148c93ca3894295a4a6b1e9aa870..bd8d98aa813b575e83138e79726bd314
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.scoreboard) {
+ ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
+ }
+ // Lophine start - Add a config to enable scoreboard command
SeedCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
VersionCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
+ // Lophine end - Add a config to enable scoreboard command
SeedCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
VersionCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
SetBlockCommand.register(this.dispatcher, context);
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Thu, 4 Jun 2026 00:56:32 +0800
Subject: [PATCH] Add config to enable trigger command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 87ffca5ff0c2775cb85a6058c9be66e00c94f01f..74ef76058e5a410d12f88aa09450e7d90f63b5e6 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -274,7 +274,11 @@ public class Commands {
// Luminol end - Add a config to enable tick command
TimeCommand.register(this.dispatcher, context);
TitleCommand.register(this.dispatcher, context);
- //TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Lophine start - Add a config to enable trigger command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.trigger) {
+ TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Lophine end - Add a config to enable trigger command
if (me.earthme.luminol.config.modules.experiment.CommandConfig.waypointsAndWaypointCommand) WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later // Luminol - Restore waypoints
WeatherCommand.register(this.dispatcher);
WorldBorderCommand.register(this.dispatcher);
@@ -5,35 +5,36 @@ 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 bca2c5410aa543d2bb421e53893e9163508b3568..fdccb06c918d387e46c29ede7337159db8c5d9ca 100644
index 0c0775bbb0c0ba0c37d1b884bb106b5250e94750..0dfb25ad032429a2aea7aa441dd5fd1848a6c617 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1350,7 +1350,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
double d1 = vec3_dx * vec3_dx + vec3_dz * vec3_dz; // Paper
double d2 = d * d;
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 040c0f8d26554ba583ecf370e2df3690d8f48dd6..22e68cabb4554c3e21e6f4ef316186f60ec77511 100644
index 552fd994ee30deb6e9f4228b17a2883cf26b164c..f090b8d77bd2731debfc61c263bd77550f52212b 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -152,7 +152,7 @@ import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
-public abstract class Entity implements SyncedDataHolder, DebugValueSource, Nameable, ItemOwner, SlotProvider, 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, DebugValueSource, Nameable, ItemOwner, SlotProvider, 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;
static boolean isLevelAtLeast(ValueInput input, int level) {
@@ -6442,4 +6442,46 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -6432,4 +6432,48 @@ public abstract class Entity
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
+ // Lophine start - Add config to enable raytracing tracker
+
+ private long lasttime = 0;
+ private boolean culled = false;
@@ -76,26 +77,29 @@ index 040c0f8d26554ba583ecf370e2df3690d8f48dd6..22e68cabb4554c3e21e6f4ef316186f6
+ return this.outOfCamera;
+ }
+
+ // Lophine end - Add config to enable raytracing tracker
}
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 0590d5723854a03a59fe9471710802f4e64e50b8..4f8ff2c024d6f2e67c5fa38fe2e660ba39e35499 100644
index cb0a52dc3795e1cf54069bcbe82abf7877a658b8..0d743a01ae70baa789cd0e0bb9abd4c4f8310b99 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1254,6 +1254,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1252,6 +1252,11 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
public final int passengerTickTimerId;
public final int passengerInactiveTickTimerId;
// Folia end - profiler
+ // Lophine start - Add config to enable raytracing tracker
+ // Luminol - Raytracing entity tracker
+ public boolean skipRaytracningCheck = false;
+ // Luminol end
+ // Lophine end - Add config to enable raytracing tracker
public EntityType(
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 67c0f4027a1e8b364694b5ed8b71965f2fe9b359..0f6e1428cc71c370af45db3e2a4f47c66e5d8628 100644
index 234124cc64e5175c20f9e9f0f482c9c677bca563..b45481f781f3556001af89704b718d6291ba1f66 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -189,6 +189,25 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -185,6 +185,25 @@ public abstract class Player extends Avatar implements ContainerUser {
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
}
// CraftBukkit end
@@ -119,9 +123,9 @@ index 67c0f4027a1e8b364694b5ed8b71965f2fe9b359..0f6e1428cc71c370af45db3e2a4f47c6
+ }
+ // Luminol end
public Player(Level level, GameProfile gameProfile) {
public Player(final Level level, final GameProfile gameProfile) {
super(EntityType.PLAYER, level);
@@ -245,6 +264,26 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -240,6 +259,26 @@ public abstract class Player extends Avatar implements ContainerUser {
@Override
public void tick() {
@@ -148,7 +152,7 @@ index 67c0f4027a1e8b364694b5ed8b71965f2fe9b359..0f6e1428cc71c370af45db3e2a4f47c6
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
@@ -1353,6 +1392,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -1352,6 +1391,7 @@ public abstract class Player extends Avatar implements ContainerUser {
if (this.hasContainerOpen()) {
this.doCloseContainer();
}
@@ -0,0 +1,123 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add tick rate support
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 981f63b75584dbcb4bb0d5672e8c8bb140c52f9d..6e8ee04967afa410ce9dccff34bf9a43201694fd 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -371,6 +371,14 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Lophine start - Add a config to enable tick command
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ rateManager.reduceSprintTicks();
+ rateManager.endTickWork();
+ }
+ // Lophine end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 86c51506c518ee445d00f7eef36ee2c9adbd9b4c..a37f392146ccc0319cf56ee0058ae8782b598fe3 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Lophine - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Lophine - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -509,8 +509,24 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Lophine start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ if (rateManager.isSprinting() && rateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = rateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Lophine end - Add a config to enable tick command
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index 8d0f810100a4eac65831913feeb9a9eeb0e6006a..ca35415e152dc63cb9f4ae8da8b06766600922fd 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Lophine start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Lophine end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index cae943bae4701f74b46a49d68da83ae797841590..9f43eff6160ac6855c2e5dd9c23c384b03b7e96c 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Lophine - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -22,14 +22,14 @@ public class TickCommand {
Commands.literal("tick")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
-/* .then(
+ .then( // Lophine - Add tick rate support
Commands.literal("rate")
.then(
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
)
- )*/
+ )
.then(
Commands.literal("step")
.executes(c -> step(c.getSource(), 1))
@@ -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 8e08cb90dc94171a8da7126fe18c46eaa49a58f2..a7804a0d099c79c81eb45eb20402a001d8734529 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 1281eadb2d0c5b4ce5e3afd51d8205f9a4ef011c..b1446dfb4689174ee9f55cec6080622ec34de250 100644
--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -54,7 +54,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);
- 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 6d0bb9868e2c2ef516de7630442808c04ba47b39..1a749d9bee139975fa249839df93c3a1e48bf102 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3162,7 +3162,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;
@@ -3198,7 +3198,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;
}
@@ -3415,6 +3415,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.
@@ -3526,7 +3527,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();
@@ -3568,6 +3569,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 b63cecafd841b97a694f6d2610141dcdb8f30574..392678778dc2a036c1e3db4b6bb2800e452d3cd0 100644
--- a/net/minecraft/world/Container.java
+++ b/net/minecraft/world/Container.java
@@ -37,6 +37,12 @@ public interface Container extends Clearable, SlotProvider, Iterable<ItemStack>,
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 0233c2b5e40c33330870e598431897a2ff98c2a3..3cf1819a9c82da2d2e0c43187e204353e3643369 100644
--- a/net/minecraft/world/SimpleContainer.java
+++ b/net/minecraft/world/SimpleContainer.java
@@ -210,7 +210,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();
}
@@ -285,7 +285,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 16c42a5e35c6ee1df640e5831818099fab6338f1..f3f067c62dc024a747d059608ae7a2e8740dbff2 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -271,10 +271,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 41e59f3739945ca7f6ab710c993b5c0f15fcd529..b849b04f227b43d036f4f6b3ae7accfafc389d9f 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(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
@@ -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, 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;
@@ -421,7 +423,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 00dbc0d125b2c8c208ffa46f9084c6317efaba90..1f57b3c60fd0cbfdd65e06f8994525ade6dc6bd9 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(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 44276ba9c7aab306cfd12833a834ebe61cf64e7c..0a19a7782f3fa27c41e02393e887ba7cc727012b 100644
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
@@ -162,7 +162,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 @Nullable SlotAccess getChestVehicleSlot(final int slot) {
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index 3b1c6a2397950ceb167890961b635cc69aaf8950..e7ea8849e8fa942709f505145e8076f064476206 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -292,6 +292,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);
@@ -448,7 +455,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));
@@ -556,7 +563,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);
@@ -618,7 +625,7 @@ public abstract class AbstractContainerMenu {
Slot slot2 = this.slots.get(slotIndex);
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() && slotIndex >= 0) {
Slot slot2 = this.slots.get(slotIndex);
@@ -653,15 +660,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());
}
}
@@ -763,7 +770,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();
@@ -864,7 +871,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;
}
@@ -872,7 +879,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();
};
}
@@ -895,7 +902,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 a4203c416c7a83557055099a9ea8f43ac2b18b21..46c8026876e851ec4a31fd34c9b64623469ffb8d 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(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 2b7e245ebf3bb471a1d817c4b5d56a64790cbab7..00083df87439ff0fa56e09853931b60579520d0e 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
}
public @Nullable Identifier getNoItemIcon() {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index ed2971b54afbebe37a7ff61798778a4249b79856..73a97f4f62fe7d27b441cab58c6c86ffce011060 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -174,7 +174,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
private int popTime;
@Deprecated
private @Nullable Item item;
- PatchedDataComponentMap components;
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
private @Nullable Entity entityRepresentation;
public static DataResult<ItemStack> validateStrict(ItemStack stack) {
@@ -200,7 +200,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);
}
}
@@ -209,13 +210,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);
}
@@ -309,7 +312,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 c5fe15844d405a27cdae18c903dd481c25b437de..3faa541c4a4623e915269d6241e1a3a3c6e374ff 100644
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -191,7 +191,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 9346f2deca8eeca29fa2fced416247fd1609249e..07236e86638faa3231917af507cdd37ac49b1270 100644
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -412,7 +412,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 8f80c469c309bf61328c4f98037495f47a38c3c1..b4127d4b4386b98205275a9a0ef8067ccf287e67 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(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 f851e0f7d727cb9dca70c578777d871af424388c..6a51bace3151646afae9de820d9c8977a0221df4 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -145,7 +145,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
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
@@ -741,9 +741,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 - vanilla hopper
@@ -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);
@@ -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 dcdd6f230ff153a7b58d13b963d32376b1905b72..be9c78f2cf121e8ae55c1b18685877637a25ec80 100644
--- a/net/minecraft/world/entity/raid/Raid.java
+++ b/net/minecraft/world/entity/raid/Raid.java
@@ -264,7 +264,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 {
@@ -341,7 +341,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) {
@@ -396,7 +402,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);
@@ -408,7 +421,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;
@@ -702,7 +715,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;
@@ -721,6 +734,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)) {
@@ -883,4 +926,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 5e8245e6dd8a07ece83dd1bc20e351a92044e7a0..2b7894a4104d4cb237746a3e66d4368b6f8f3c1e 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -127,6 +127,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().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(damageSource);
@@ -5,15 +5,15 @@ 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 7a9394d4555464312418964f1a7a5d2581496774..3fcd32cc77458ce196ce0e468c1a99f456a57604 100644
index 0008aa0ca02fc4ea67b795b3f0a0e9656233ce89..2734ffc103ee4760d3521609fdd090ab99df675b 100644
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
@@ -314,7 +314,7 @@ public class Zombie extends Monster {
int floor = Mth.floor(this.getX());
int floor1 = Mth.floor(this.getY());
int floor2 = Mth.floor(this.getZ());
@@ -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 zombie = type.create(level, EntitySpawnReason.REINFORCEMENT);
if (zombie == null) {
Zombie reinforcement = type.create(level, EntitySpawnReason.REINFORCEMENT);
if (reinforcement == null) {
return true;
@@ -5,10 +5,10 @@ Subject: [PATCH] Spawn invulnerable time
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index ec34282744c71c881392ff278a8b03af90de8151..f0d45cb70af62b747c9235941f3fc45221b3b8e6 100644
index 338e0c7c09120c6e9617893dd074cbd5da40a093..baab2435bac22aacff30ad52bde629b4093bfaba 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -240,6 +240,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;
@@ -16,7 +16,7 @@ index ec34282744c71c881392ff278a8b03af90de8151..f0d45cb70af62b747c9235941f3fc452
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
public ParticleStatus particleStatus = ParticleStatus.ALL;
private boolean canChatColor = true;
@@ -898,6 +899,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -920,6 +921,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.connection.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
@@ -24,17 +24,17 @@ index ec34282744c71c881392ff278a8b03af90de8151..f0d45cb70af62b747c9235941f3fc452
if (this.invulnerableTime > 0) {
this.invulnerableTime--;
}
@@ -1536,6 +1538,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 0b5f2060062a354bd6cafa8f53a5734dc83d062d..e15be199d690954d99d710de4046e721a943b3a9 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 65d5c766eb9bfade4d8259bda418a7f0e413edbe..b052bc0107d93cd65a6c92914d6b3d02d6cc5ccb 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 06d55281bb782cc064255c7b56acd6cd332b9085..d926be9a0c4954746032e3e96cf50a8cba5f26b3 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
@@ -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);
@@ -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 5bae274f5ee869e540e4330e03af671b6b18313d..3fe9afe55b4d61db8030479d3d74b8656679cb10 100644
index cc7b2ea7fda1326e3f9ed46373190a05f60c4d34..2bce20202b7c539bee3685741663a8ed225919ff 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1240,6 +1240,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 5bae274f5ee869e540e4330e03af671b6b18313d..3fe9afe55b4d61db8030479d3d74b865
+ 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 2b7894a4104d4cb237746a3e66d4368b6f8f3c1e..03e3290367790add702a5856aaff3be465ea548c 100644
index 1a51da9171c13711e106731c360051d183a40893..7094a67959e9747b2dfa55a5f5a3e90552d35466 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -157,7 +157,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);
@@ -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, 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
+ 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);
}
@@ -1,66 +1,66 @@
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 80b5d151e0dd6fa44794187875b4b80519839d81..8d32d906f87a1cb866a7497ee0de3045e9adce2c 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -369,6 +369,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 1da034752064312962a4144f91be5265a9a08997..081ca42b6a6644eb8c2b5ac9105fecf8ad39d501 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) {
Identifier identifier = buffer.readIdentifier();
- return (CustomPacketPayload)this.findCodec(identifier).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(identifier, buffer);
+ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(identifier).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 82013a8f7cf07b6f0645ca6b51ee75fcb0a56298..54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e 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 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707678da7a3 100644
index cf4b5e436b8d81657d1deaa5b06645016d9dc3cc..f3af5660a377e2eb823f79ec274feaf3284761cd 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -58,6 +58,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -57,6 +57,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
public @Nullable String playerBrand;
public final java.util.Set<String> pluginMessagerChannels;
// 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;
@@ -71,6 +72,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -70,6 +71,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
this.pluginMessagerChannels = cookie.channels();
this.keepAlive = cookie.keepAlive();
// Paper end
@@ -68,10 +68,10 @@ index 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707
}
// Paper start - configuration phase API
@@ -161,6 +163,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);
@@ -87,7 +87,7 @@ index 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707
// Paper start
if (!(packet.payload() instanceof final net.minecraft.network.protocol.common.custom.DiscardedPayload discardedPayload)) {
return;
@@ -220,10 +234,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 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707
} else {
bridge.removeChannel(channel);
}
- // Paper end
+ // Paper end
}
@Override
@@ -386,9 +401,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
);
@@ -421,10 +436,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 d2b2bf35b3f5704f3bca94d0fe3b70206c2fbf96..c8be04b8a50bac52150a1fdd238634e630e1765e 100644
index 527c495bb4f6007aee760b99cc0e9aa589931f4b..e6987eaf6e4d36d43cee4ece3ce22d31052a2a2a 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -315,6 +315,8 @@ public abstract class PlayerList {
@@ -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();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -511,6 +513,7 @@ public abstract class PlayerList {
@@ -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 net.kyori.adventure.text.@Nullable 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);
@@ -1401,6 +1404,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
}
@@ -4,14 +4,14 @@ 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)
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 d0b5bc9da450d881534abdbd8ff786e1fbc7d418..674450fb2e600236f99550febf276d093308b8d8 100644
index 0f1bd15ea3b1400cc948883c92eceabcd4a4cda1..006844d6fda43f3b151899655f03b1de03f3396c 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -3030,7 +3030,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -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
@@ -21,26 +21,26 @@ index d0b5bc9da450d881534abdbd8ff786e1fbc7d418..674450fb2e600236f99550febf276d09
}
// 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 c8be04b8a50bac52150a1fdd238634e630e1765e..2eb551390aa66d89988df9ca23cf0dd7ccfd6577 100644
index e6987eaf6e4d36d43cee4ece3ce22d31052a2a2a..168702a5ae51a2bc42c5761e13cb14008a8162c4 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -555,7 +555,7 @@ public abstract class PlayerList {
@@ -560,7 +560,7 @@ public abstract class PlayerList {
player.stopRiding();
rootVehicle.getPassengersAndSelf().forEach(entity -> {
vehicle.getPassengersAndSelf().forEach(e -> {
// Paper start - Fix villager boat exploit
- if (entity instanceof net.minecraft.world.entity.npc.villager.AbstractVillager villager) {
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity instanceof net.minecraft.world.entity.npc.villager.AbstractVillager villager) { // Leaves - Configurable trading with the void
- 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 6dfee62a46a5882df7f405e59d762647289d7866..1192a6ab33a9481397b84c9cf0a24fbbcb0ed065 100644
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(Player player) {
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,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 95f6b1cbd5e33151c326689bc72292ff38a48803..e1974bbebbd10b75ea02955d9ced198d54c8a6f1 100644
index ca35415e152dc63cb9f4ae8da8b06766600922fd..033715812acb8f98a7c7d895d115043e232d5161 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -135,4 +135,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,10 +23,10 @@ index 95f6b1cbd5e33151c326689bc72292ff38a48803..e1974bbebbd10b75ea02955d9ced198d
+ // Leaves end - servux
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 674450fb2e600236f99550febf276d093308b8d8..f5bf8ed6e741823078ab93eac47636fcebcdfe2d 100644
index 006844d6fda43f3b151899655f03b1de03f3396c..0befa4fc81e10a23c6ba824e559f2fb4886e68ee 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2463,6 +2463,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2584,6 +2584,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
this.server.updateEffectiveRespawnData();
}
// Paper end
@@ -5,7 +5,7 @@ Subject: [PATCH] LeavesHooks
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
index faf62f8c9453f8e7a21b1e141577f1f4539cd2f9..4e5985a3e4969f466980558190324350019ba8af 100644
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;
@@ -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 08a1be57e1057a9e961eeb8f59cd12e98ed52bab..33ee967d8a7d4ce2c455db9ffaac740cd589e6f3 100644
index 769dc39e11881d5f81a2405850cbcbd0842c5995..9fc97e8b01f66ada6af1fe76f4e27c9bb1a5dcfc 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -717,6 +717,7 @@ public class ServerExplosion implements Explosion {
@@ -708,6 +708,7 @@ public class ServerExplosion implements Explosion {
public boolean shouldAffectBlocklikeEntities() {
boolean flag = this.level.getGameRules().get(GameRules.MOB_GRIEFING);
boolean flag1 = 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) flag1 = flag1 && (this.source == null || !this.source.isInWater()); // Leaves - Old MC TNT wet explosion no item damage
return flag ? flag1 : this.blockInteraction.shouldAffectBlocklikeEntities() && flag1;
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;
}
@@ -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 5e25ddf78f72ada318ef28d29199de9b93fe667e..6f48162a25e20d2439935e8995cede9497626322 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 5e25ddf78f72ada318ef28d29199de9b93fe667e..6f48162a25e20d2439935e8995cede94
} 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,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 f3f067c62dc024a747d059608ae7a2e8740dbff2..1b8a963726ee2b2244d429f1e7e3a08034bfbd70 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -283,7 +283,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);
@@ -1,5 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 3 Feb 2025 16:51:01 +0800
Subject: [PATCH] Leaves: Syncmatica Protocol
@@ -9,10 +9,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1a749d9bee139975fa249839df93c3a1e48bf102..d81e22fe65cded98c201a7bbae8a51b22c6a20b4 100644
index e15be199d690954d99d710de4046e721a943b3a9..0eae303f8959345571a906906ef60c6a28bba348 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -338,9 +338,12 @@ public class ServerGamePacketListenerImpl
@@ -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
@@ -1,5 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 3 Feb 2025 13:03:42 +0800
Subject: [PATCH] Leaves: BBOR Protocol
@@ -8,12 +8,12 @@ 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 435acf0fe5e80ca371d1145befc2cfaa917a89e3..77577d0df9b14a7ad55b2866c2ac31863226458b 100644
index da9706f866aabee6939cacbfbcc9def01fde0326..3708f9ffc46a5b1c038c0e7b2ce84802e2b22397 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -758,6 +758,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -772,6 +772,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
public void setLoaded(boolean loaded) {
public void setLoaded(final boolean loaded) {
this.loaded = loaded;
+ // Leaves start - bbor
+ if (loaded) {
@@ -1,5 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 7 Feb 2025 14:23:43 +0800
Subject: [PATCH] Leaves: Xaero Map Protocol
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 3a5319739f0687fc6f09b2ac8ee31716593fe0de..36cd1a0307ff1a734eb5f4f3cc013781692e7ad8 100644
index 168702a5ae51a2bc42c5761e13cb14008a8162c4..ebd2f2887780d9c6c3c44983bac23eab732cf43f 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1126,6 +1126,7 @@ public abstract class PlayerList {
@@ -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
@@ -1,5 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Thu, 27 Mar 2025 13:04:35 +0800
Subject: [PATCH] Leaves: Support REI protocol
@@ -8,16 +8,16 @@ 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 d02609198253b51f632db46c40afd737d686c520..7296e0b73f1c8e32374f39238d1dfac62bc41afb 100644
index 33f9870a4f966a887023b1debd4ab9ef9d24378f..89983e7da244434a5346b23b49c748349cd79e34 100644
--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
+++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
@@ -82,6 +82,12 @@ public class SmithingTransformRecipe implements SmithingRecipe {
@@ -115,6 +115,12 @@ public class SmithingTransformRecipe extends SimpleSmithingRecipe {
);
}
+ // Leaves start - REI
+ public SlotDisplay getResult() {
+ return this.result.display();
+ return new SlotDisplay.ItemStackSlotDisplay(this.result);
+ }
+ // Leaves end - REI
+
@@ -25,10 +25,10 @@ index d02609198253b51f632db46c40afd737d686c520..7296e0b73f1c8e32374f39238d1dfac6
@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 6582370cfa3d58a7ac08d574e26e7a93d243bdaa..07501a27e6032e578b823d9b617166a9e78fcb20 100644
index f9fa7d0eaf9f32959a4bd12b82e5a49ea808a44c..2f3241563ad7e5ed5663b913671d2af056df97bb 100644
--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
+++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
@@ -84,6 +84,12 @@ public class SmithingTrimRecipe implements SmithingRecipe {
@@ -109,6 +109,12 @@ public class SmithingTrimRecipe extends SimpleSmithingRecipe {
return Optional.of(this.addition);
}
@@ -40,4 +40,4 @@ index 6582370cfa3d58a7ac08d574e26e7a93d243bdaa..07501a27e6032e578b823d9b617166a9
+
@Override
public RecipeSerializer<SmithingTrimRecipe> getSerializer() {
return RecipeSerializer.SMITHING_TRIM;
return SERIALIZER;
@@ -8,24 +8,11 @@ Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 132645758827ee4d332909e701dde24e69699beb..3efce8ae3cba85019aea7453f97a72939baef7f6 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1451,7 +1451,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
} 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, damageSource);
}
// Luminol End - Cross Region Damage trace
}
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index d81e22fe65cded98c201a7bbae8a51b22c6a20b4..43e9fd5684d15f8643524132e60266071c6dc454 100644
index 0eae303f8959345571a906906ef60c6a28bba348..1af966cadec3dd51aae842824e432e20b700d9c9 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3835,7 +3835,7 @@ public class ServerGamePacketListenerImpl
@@ -3902,7 +3902,7 @@ public class ServerGamePacketListenerImpl
}
@Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add PlayerLoadedWorldEvent
@@ -35,10 +22,10 @@ index d81e22fe65cded98c201a7bbae8a51b22c6a20b4..43e9fd5684d15f8643524132e6026607
this.markClientLoaded(false);
}
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
index 901e4e9897e76cd4158d7f8bb8ec829df8ff8196..59b9373c7a14e42d9e5f691354a7616d16856215 100644
index 03ec05a860781f85e58055d6f58893963781bd97..c15f0a3d419fea50d4349fa864e83bf7fee78b9f 100644
--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java
+++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
@@ -64,7 +64,7 @@ public class Armadillo extends Animal {
@@ -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();
@@ -46,12 +33,12 @@ index 901e4e9897e76cd4158d7f8bb8ec829df8ff8196..59b9373c7a14e42d9e5f691354a7616d
+ public int scuteTime; // Leaves - private -> public
private boolean peekReceivedClient = false;
public Armadillo(EntityType<? extends Animal> type, Level level) {
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 f65cfb908aac16e6df4d209c6b5c3ee5065289d3..9afada8ca16775752468e1b14cd97daf26325fc4 100644
index 3d4bfeae2fddb9ace26e7dea8870704d8309862b..d2862d2e6f599265bc319000bba05609e0bea2c3 100644
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
@@ -244,7 +244,7 @@ public class Tadpole extends AbstractFish {
@@ -255,7 +255,7 @@ public class Tadpole extends AbstractFish {
}
}
@@ -61,12 +48,12 @@ index f65cfb908aac16e6df4d209c6b5c3ee5065289d3..9afada8ca16775752468e1b14cd97daf
}
diff --git a/net/minecraft/world/level/storage/loot/LootPool.java b/net/minecraft/world/level/storage/loot/LootPool.java
index 43b8f4674602532f0273ebc5a0233476d10f6735..2ed995e68cf7812c74c3ba15b49450b2b5f3f0f8 100644
index f08a25b76e689c2242e8ef8226c3d8c2dcec1c70..6e76e472bd1e7242f6cd7986c23ebc38d16fd46a 100644
--- a/net/minecraft/world/level/storage/loot/LootPool.java
+++ b/net/minecraft/world/level/storage/loot/LootPool.java
@@ -37,7 +37,7 @@ public class LootPool {
@@ -36,7 +36,7 @@ public class LootPool implements Validatable {
)
.apply(instance, LootPool::new)
.apply(i, LootPool::new)
);
- private final List<LootPoolEntryContainer> entries;
+ public final List<LootPoolEntryContainer> entries; // Leaves - private -> public
@@ -74,10 +61,10 @@ index 43b8f4674602532f0273ebc5a0233476d10f6735..2ed995e68cf7812c74c3ba15b49450b2
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 35b5154473a3021dcae1f2ad016a77bcfb058c58..3d338b354c3d558a1c4ec20c149e8f26ed27da1e 100644
index 14fc07badbd14a5a4c8e8c7d237d08a4eb6a6f12..0aaf2240a0f79b5c4aaa9c22dca7b2f0953dac49 100644
--- a/net/minecraft/world/level/storage/loot/LootTable.java
+++ b/net/minecraft/world/level/storage/loot/LootTable.java
@@ -50,7 +50,7 @@ public class LootTable {
@@ -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;
@@ -87,10 +74,10 @@ index 35b5154473a3021dcae1f2ad016a77bcfb058c58..3d338b354c3d558a1c4ec20c149e8f26
private final BiFunction<ItemStack, LootContext, ItemStack> compositeFunction;
public org.bukkit.craftbukkit.CraftLootTable craftLootTable; // CraftBukkit
diff --git a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
index eeaa49e9f70a18b5d39493aeff73f31b05ac2faa..8cd0403d7873c4c37caef75935b06b056c3d951d 100644
index 53e4375a4af610e54309f2978e59985e6ada15f5..615b533caecef09d967c615ae39ef29c80784575 100644
--- a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
+++ b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
@@ -16,7 +16,7 @@ public abstract class CompositeEntryBase extends LootPoolEntryContainer {
@@ -17,7 +17,7 @@ public abstract class CompositeEntryBase extends LootPoolEntryContainer {
return "Empty children list";
}
};
@@ -98,22 +85,22 @@ index eeaa49e9f70a18b5d39493aeff73f31b05ac2faa..8cd0403d7873c4c37caef75935b06b05
+ public final List<LootPoolEntryContainer> children; // Leaves - private -> public
private final ComposableEntryContainer composedChildren;
protected CompositeEntryBase(List<LootPoolEntryContainer> children, List<LootItemCondition> conditions) {
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 cfa05e882d2987cfab4c9d555a2de065b29fdf7e..4bacc9e2fb94d1b24887e7f0e9ce628814393209 100644
index 83c514c213251dd5470627d0299b5858b850784d..d231f706388e6967d2e29f806a9f52e8f7f5ba61 100644
--- a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
+++ b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
@@ -14,7 +14,7 @@ import net.minecraft.world.level.storage.loot.predicates.ConditionUserBuilder;
@@ -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 {
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(List<LootItemCondition> conditions) {
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 141026601cd9a4561426b85fd1f8e7dc0544fbd7..a5d7ebb93c147bf0f806ac3c9b2dc4b878573944 100644
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 {
@@ -124,12 +111,12 @@ index 141026601cd9a4561426b85fd1f8e7dc0544fbd7..a5d7ebb93c147bf0f806ac3c9b2dc4b8
+ public final Either<ResourceKey<LootTable>, LootTable> contents; // Leaves - private -> public
private NestedLootTable(
Either<ResourceKey<LootTable>, LootTable> contents, int weight, int quality, List<LootItemCondition> conditions, List<LootItemFunction> functions
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 bae72197acc929c7ed3e964f156115d728eb2176..8f3094f42f3366a1313d70c0b27fbe5632b2082a 100644
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.LootContext;
@@ -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 {
@@ -137,4 +124,4 @@ index bae72197acc929c7ed3e964f156115d728eb2176..8f3094f42f3366a1313d70c0b27fbe56
+ public final List<LootItemCondition> terms; // Leaves - private -> public
private final Predicate<LootContext> composedPredicate;
protected CompositeLootItemCondition(List<LootItemCondition> terms, Predicate<LootContext> composedPredicate) {
protected CompositeLootItemCondition(final List<LootItemCondition> terms, final Predicate<LootContext> composedPredicate) {
@@ -1,5 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 3 Feb 2025 13:51:26 +0800
Subject: [PATCH] Leaves: Alternative block placement Protocol
@@ -13,62 +13,62 @@ 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 43e9fd5684d15f8643524132e60266071c6dc454..62db0ba9c824959f953d452ab7aafcde01b10bcd 100644
index 1af966cadec3dd51aae842824e432e20b700d9c9..83c9418ea45b8d7f639c6bf5e134bad90d9ac039 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2134,7 +2134,7 @@ public class ServerGamePacketListenerImpl
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.level(), blockPos.getX() >> 4, blockPos.getZ() >> 4, 8) && this.player.isWithinBlockInteractionRange(blockPos, 1.0)) { // Folia - do not allow players to interact with blocks outside the current region
Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos));
double d = 1.0000001;
- if (Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) {
+ if (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.needIgnoreDistance() ||Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) { // Leaves - disableDistanceCheckForUseItem
Direction direction = hitResult.getDirection();
@@ -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 = this.player.level().getMaxY();
int maxY = level.getMaxY();
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 73ce7c82c0bd28c2e43ca40ba35c4603b21375ad..a5d3caab2072b2c9bf8fdcbdb7c52c2dee16cfaf 100644
index 3167be4b7c2c61ef725af4a832d759ab6e061af0..2e2a8af12f249ec5bd0935fd13f5acbd0a777b5f 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -147,7 +147,7 @@ public class BlockItem extends Item {
@@ -136,7 +136,7 @@ public class BlockItem extends Item {
}
protected @Nullable BlockState getPlacementState(BlockPlaceContext context) {
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 d75c95d728efc0b4064f562ca80b68b23883feaf..be685383b8e7c8111e976fc560f16d43d6545a34 100644
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(BlockPlaceContext context) {
- BlockState stateForPlacement = this.wallBlock.getStateForPlacement(context);
+ BlockState stateForPlacement = this.wallBlock.getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
BlockState blockState = null;
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 clickedPos = context.getClickedPos();
BlockPos pos = context.getClickedPos();
for (Direction direction : context.getNearestLookingDirections()) {
if (direction != this.attachmentDirection.getOpposite()) {
- BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : stateForPlacement;
+ BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getRealStateForPlacement(context) : stateForPlacement; // Leaves - alternativeBlockPlacement
if (blockState1 != null && this.canPlace(level, blockState1, clickedPos)) {
blockState = blockState1;
- 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 492b1615d96133c5082e0f16015f114299f8082f..fb47a2acb0e4232359f5da061c1620a7b1d6c476 100644
index c5f4e0570a82dfcc2ba88023f3301f69afa41cc5..30f7e8f5e3e9440713e36ee25c90150b6b93c6ff 100644
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -489,6 +489,32 @@ public class Block extends BlockBehaviour implements ItemLike {
public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) {
@@ -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(BlockPlaceContext context) {
+ 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 -> {
@@ -93,6 +93,6 @@ index 492b1615d96133c5082e0f16015f114299f8082f..fb47a2acb0e4232359f5da061c1620a7
+ }
+ // Leaves end - alternativeBlockPlacement
+
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
public @Nullable BlockState getStateForPlacement(final BlockPlaceContext context) {
return this.defaultBlockState();
}
@@ -8,19 +8,19 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java b/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
index 368a9d33f93c2e85abe4cf10df5a85c09fb03dd6..2b78040daeb3b09c08494cbc1d4a9d36080895f9 100644
index dfce5ced082de0caaff8da071fb632cd6ae787c9..d5c1862ebf6066859da74f47fa0be0256ba0f653 100644
--- a/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
+++ b/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
@@ -39,6 +39,7 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
@@ -41,6 +41,7 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
}
protected void trigger(ServerPlayer player, Predicate<T> testTrigger) {
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>> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
if (set != null && !set.isEmpty()) {
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 9f444988d40208a1bfa9f147ef80489f81115e93..ab2fa0b86564622501238305714fff014e2b2a56 100644
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<?>> {
@@ -28,61 +28,66 @@ index 9f444988d40208a1bfa9f147ef80489f81115e93..ab2fa0b86564622501238305714fff01
// Spigot end
private volatile @Nullable PacketListener disconnectListener;
- private volatile @Nullable PacketListener packetListener;
+ public volatile @Nullable PacketListener packetListener; // Leaves - private -> protected // Lophine protected -> public
+ 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 8d96d2130cf3383427047fee97fa49155164e337..dfcf8eb7dc422a55d94d6eb9eb1451c7c14a1d56 100644
index 54ba8a2bc70f3a7f9754a872f6b9c22b40887d8e..c4685bb540e95d889dfbc107923876045be29848 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -425,6 +425,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Folia end - regionised ticking
@@ -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(Function<Thread, S> threadFunction) {
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> atomicReference = new AtomicReference<>();
@@ -1050,6 +1052,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()) {
AtomicReference<S> serverReference = new AtomicReference<>();
@@ -1226,6 +1228,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.safeShutdown(wait, false);
}
public void safeShutdown(final boolean wait, final boolean isRestarting) {
+ // Lophine start - Folia changes
+ safeShutdown(wait, isRestarting, false);
+ }
+
+ public void safeShutdown(final boolean wait, final boolean isRestarting, boolean force) {
+ if (!force && !this.getBotList().forceShutdown && !this.getBotList().removeAll()) { // Leaves - save or remove bot
+ this.getPlayerList().broadcastSystemMessage(Component.literal("Bot Still need to save, please wait! If you want to shuntdown without bot data saving, please use /stop force"), false);
+ return;
+ }
+ // Leaves end - save or remove bot
// Folia start - region threading
// halt scheduler
// don't wait, we may be on a scheduler thread
@@ -1668,7 +1675,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = this.pauseWhenEmptySeconds() * 20;
+ // Lophine end - Folia changes
this.isRestarting = isRestarting;
this.hasLoggedStop = true; // Paper - Debugging
if (this.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
@@ -1695,7 +1707,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int emptyTickThreshold = this.pauseWhenEmptySeconds() * 20;
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
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;
@@ -1801,6 +1808,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1827,6 +1839,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isSaving = true;
if (playerSaveInterval > 0) {
this.playerList.saveAll(playerSaveInterval);
+ org.leavesmc.leaves.bot.BotList.INSTANCE.saveAllResumeBots(playerSaveInterval); // Leaves - resident fakeplayer
}
for (final ServerLevel level : (region == null ? this.getAllLevels() : Arrays.asList(region.world))) { // Folia - region threading
if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
@@ -2021,6 +2029,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (region == null && fullSave) { // Folia - region threading - don't auto save level data
this.saveGlobalData(false);
@@ -2065,6 +2078,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void tickConnection() {
protected void tickConnection() {
this.getConnection().tick();
+ this.botList.networkTick(); // Leaves - fakeplayer
}
private void synchronizeTime(ServerLevel level) {
@@ -3155,6 +3164,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void forceGameTimeSynchronization() {
@@ -3270,6 +3284,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.debugSubscribers;
}
@@ -100,127 +105,144 @@ index 8d96d2130cf3383427047fee97fa49155164e337..dfcf8eb7dc422a55d94d6eb9eb1451c7
@Override
public void close() {
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
index c9e6cd428e4c74b14a992de9ffe85a5a707c4e6b..5bf7eb5b906cefa57a1dfcf828ff7872dbceac4f 100644
index 658db8460122db271bbc3c2c0844574b8d75f044..89448eee9f135de8b406bf5f4147b3298e33ba17 100644
--- a/net/minecraft/server/PlayerAdvancements.java
+++ b/net/minecraft/server/PlayerAdvancements.java
@@ -166,6 +166,11 @@ public class PlayerAdvancements {
@@ -168,6 +168,11 @@ public class PlayerAdvancements {
}
public boolean award(AdvancementHolder advancement, String criterionKey) {
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 flag = false;
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
boolean isDone = orStartProgress.isDone();
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 d92492bca62fb02fe7a9e4e220cb8651c4d1e16d..7d0752f9a6a90cf389a9cb5829ab02606266f204 100644
index 36b858bfe123edc2f1c5c7861dd0e4475ef7a5f1..e52a2ad8408d9691701dc51fa702efdb51f0acbb 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);
@@ -40,6 +40,12 @@ public class BanIpCommands {
return banIp(source, target, reason);
} else {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(username);
ServerPlayer player = source.getServer().getPlayerList().getPlayerByName(target);
+ // Leaves start - disable ban
+ if (playerByName instanceof org.leavesmc.leaves.bot.ServerBot) {
+ if (player 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);
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 978ef2e996a78e907f959bfe99d47de832427011..9644e68ba2c295fcda2d4a3034277520ade91bca 100644
index c87bc86c57fde9d92e3927bdead5cdaf2e935744..950f8ed955bc09713348936ae7aa1a8b14006c2a 100644
--- a/net/minecraft/server/commands/BanPlayerCommands.java
+++ b/net/minecraft/server/commands/BanPlayerCommands.java
@@ -45,7 +45,15 @@ public class BanPlayerCommands {
UserBanList bans = source.getServer().getPlayerList().getBans();
int i = 0;
@@ -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 nameAndId : players) {
for (NameAndId player : players) {
+ // Leaves start - disable ban
+ if (nameAndId.isBot()) {
+ if (player.isBot()) {
+ source.sendFailure(Component.literal("Permission denied"));
+ hasBot = true;
+ continue;
+ }
+ // Leaves end - disable ban
if (!bans.isBanned(nameAndId)) {
UserBanListEntry userBanListEntry = new UserBanListEntry(
nameAndId, null, source.getTextName(), null, reason == null ? null : reason.getString()
@@ -63,7 +71,13 @@ public class BanPlayerCommands {
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 (i == 0) {
if (count == 0) {
- throw ERROR_ALREADY_BANNED.create();
+ // Leaves start - disable kick
+ if (hasBot) {
+ return i;
+ return count;
+ } else {
+ throw ERROR_ALREADY_BANNED.create();
+ }
+ // Leaves end - disable kick
} else {
return i;
return count;
}
diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java
index 5f78d629bab84acb2fa43a9fcc1cec52b4e91ae3..1c6059bd23afdd555d2dc8c533a5b027957c7b3a 100644
index 0227dd63f67537d769494e122616873c18d35350..18d49018b1330cfcaa91d9b02d0d23e4ba941809 100644
--- a/net/minecraft/server/commands/KickCommand.java
+++ b/net/minecraft/server/commands/KickCommand.java
@@ -46,9 +46,17 @@ public class KickCommand {
@@ -38,9 +38,17 @@ public class KickCommand {
if (!source.getServer().isPublished()) {
throw ERROR_SINGLEPLAYER.create();
} else {
+ boolean hasBot = false; // Leaves - disable kick
int i = 0;
int count = 0;
for (ServerPlayer serverPlayer : players) {
for (ServerPlayer player : players) {
+ // Leaves start - disable kick
+ if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) {
+ 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(serverPlayer.nameAndId())) {
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 (!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 (i == 0) {
if (count == 0) {
- throw ERROR_KICKING_OWNER.create();
+ // Leaves start - disable kick
+ if (hasBot) {
+ return i;
+ return count;
+ } else {
+ throw ERROR_KICKING_OWNER.create();
+ }
+ // Leaves end - disable kick
} else {
return i;
return count;
}
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
index 07332a86e6e0441bafacb020f27ec36a277f1486..590891d70a71ab30ceae3a3cf1923745e7c20b26 100644
index 636f56bfc0e9075b257e2eb14e858975bdedd801..20cbc0e65fea3fc2d0033259c2f35e158ea81926 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;
@@ -39,6 +39,7 @@ public class OpCommand {
int count = 0;
for (NameAndId nameAndId : players) {
+ if (nameAndId.isBot()) continue; // Leaves - disable op
if (!playerList.isOp(nameAndId)) {
playerList.op(nameAndId);
i++;
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/commands/StopCommand.java b/net/minecraft/server/commands/StopCommand.java
index e9c9a468f046832e8eaa999bb57da261b4633604..2efe24c0378a80dd2750b10a54c1887816236c1a 100644
--- a/net/minecraft/server/commands/StopCommand.java
+++ b/net/minecraft/server/commands/StopCommand.java
@@ -11,6 +11,10 @@ public class StopCommand {
c.getSource().sendSuccess(() -> Component.translatable("commands.stop.stopping"), true);
c.getSource().getServer().halt(false);
return 1;
- }));
+ }).then(Commands.literal("force").requires(Commands.hasPermission(Commands.LEVEL_OWNERS)).executes(c -> {
+ c.getSource().sendSuccess(() -> Component.translatable("commands.stop.stopping"), true);
+ c.getSource().getServer().safeShutdown(false, false, true);
+ return 1;
+ })));
}
}
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 5fbcb5eac1d5449247da77b6120edbe2f2dd1d58..69cc67b7618d38e65ccb1f4c58013ef116886ad2 100644
index 1bc1e9a77dca7acfe5f989f6439f185d0d2e20a6..1790e8c141a8d3f7ccf4b11f9a28b3582325e317 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -252,6 +252,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -274,6 +274,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
// Spigot start
@@ -228,24 +250,24 @@ index 5fbcb5eac1d5449247da77b6120edbe2f2dd1d58..69cc67b7618d38e65ccb1f4c58013ef1
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();
@@ -263,6 +264,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
@@ -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
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()) {
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 fdccb06c918d387e46c29ede7337159db8c5d9ca..4cd5c5659ac098c3b7ff95efb94b1987e2dd40d0 100644
index 0dfb25ad032429a2aea7aa441dd5fd1848a6c617..215f2a40921cc8e6b181c0a34aa1bbaf843e3059 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1386,6 +1386,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
@@ -1388,6 +1388,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
}
} else {
this.removePlayer(player);
+ // Leaves start - render bot
+ if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
+ if (this.entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
+ if (bot.needSendFakeData(player)) {
+ bot.sendFakeData(player.connection, false);
+ }
@@ -255,26 +277,26 @@ index fdccb06c918d387e46c29ede7337159db8c5d9ca..4cd5c5659ac098c3b7ff95efb94b1987
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index f5bf8ed6e741823078ab93eac47636fcebcdfe2d..14516c3ebd092e6f230804145a60dc851f34230b 100644
index 0befa4fc81e10a23c6ba824e559f2fb4886e68ee..2ddcf6ae90aaaf98e2fcd8ab9995b6f0d7791856 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -220,6 +220,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final boolean tickTime; // Folia - region threading
private final RandomSequences randomSequences;
final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
@@ -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
// CraftBukkit start
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
@@ -669,6 +670,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@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.updateTickData(); // Folia - region threading - make sure it is initialised before ticked
+ this.realPlayers = Lists.newArrayList(); // Leaves - skip
this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked
}
// Folia start - region threading
@@ -2490,6 +2492,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2611,6 +2613,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
return this.players;
}
@@ -285,37 +307,37 @@ index f5bf8ed6e741823078ab93eac47636fcebcdfe2d..14516c3ebd092e6f230804145a60dc85
+ // Leaves end - fakeplayer skip
+
@Override
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
Optional<Holder<PoiType>> optional = PoiTypes.forState(oldState);
@@ -2963,6 +2971,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
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 serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
if (entity instanceof ServerPlayer player) {
ServerLevel.this.players.add(player);
+ // Leaves start - skip
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ ServerLevel.this.realPlayers.add(serverPlayer);
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ ServerLevel.this.realPlayers.add(player);
+ }
+ // Leaves end - skip
if (serverPlayer.isReceivingWaypoints()) {
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
if (player.isReceivingWaypoints()) {
ServerLevel.this.getWaypointManager().addPlayer(player);
}
@@ -3044,6 +3057,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -3172,6 +3185,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
if (entity instanceof ServerPlayer player) {
ServerLevel.this.players.remove(player);
+ // Leaves start - skip
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ ServerLevel.this.realPlayers.remove(serverPlayer);
+ if (!(player instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ ServerLevel.this.realPlayers.remove(player);
+ }
+ // Leaves end - skip
ServerLevel.this.getWaypointManager().removePlayer(serverPlayer);
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 f0d45cb70af62b747c9235941f3fc45221b3b8e6..132645758827ee4d332909e701dde24e69699beb 100644
index baab2435bac22aacff30ad52bde629b4093bfaba..cdb4a52cbd34322903144364c3686a4e1bf0fbb8 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -227,7 +227,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -229,7 +229,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false;
public ServerGamePacketListenerImpl connection;
private final MinecraftServer server;
@@ -324,7 +346,7 @@ index f0d45cb70af62b747c9235941f3fc45221b3b8e6..132645758827ee4d332909e701dde24e
private final PlayerAdvancements advancements;
private final ServerStatsCounter stats;
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
@@ -248,7 +248,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -250,7 +250,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private @Nullable Entity camera;
public boolean isChangingDimension;
public boolean seenCredits = false;
@@ -333,7 +355,7 @@ index f0d45cb70af62b747c9235941f3fc45221b3b8e6..132645758827ee4d332909e701dde24e
private @Nullable Vec3 levitationStartPos;
private int levitationStartTime;
private boolean disconnected;
@@ -1495,7 +1495,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1514,7 +1514,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Luminol End - Cross Region Damage trace
@@ -342,37 +364,37 @@ index f0d45cb70af62b747c9235941f3fc45221b3b8e6..132645758827ee4d332909e701dde24e
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
.getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS)
@@ -2132,6 +2132,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -2180,6 +2180,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
this.teleportSpectators(teleportTransition, serverLevel);
this.teleportSpectators(transition, oldLevel);
+ // 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());
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 345bdb0ff82b8cd8c63e5ff1f2dabb68a1e54b77..c9a7c1c37155e0d339b880179a5988c9a6cb3797 100644
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(String name) {
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 string = name.toLowerCase(Locale.ROOT);
String userName = name.toLowerCase(Locale.ROOT);
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
CachedUserNameToIdResolver.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
CachedUserNameToIdResolver.GameProfileInfo profileInfo = this.profilesByName.get(userName);
diff --git a/net/minecraft/server/players/NameAndId.java b/net/minecraft/server/players/NameAndId.java
index 05b4a75f6597e8613c91344d100bb7f005d169a7..9a5006362c12e972d031c48be4d30362d88d1c00 100644
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;
@@ -382,50 +404,50 @@ index 05b4a75f6597e8613c91344d100bb7f005d169a7..9a5006362c12e972d031c48be4d30362
-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(
instance -> instance.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name))
.apply(instance, NameAndId::new)
i -> i.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name))
.apply(i, NameAndId::new)
);
public NameAndId(GameProfile profile) {
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(com.mojang.authlib.yggdrasil.response.NameAndId nameAndId) {
- this(nameAndId.id(), nameAndId.name());
+ this(nameAndId.id(), nameAndId.name(), false); // 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(JsonObject json) {
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, json.get("name").getAsString());
+ return new NameAndId(uuid, json.get("name").getAsString(), false); // Leaves - fakeplayer
- 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(String name) {
UUID uuid = UUIDUtil.createOfflinePlayerUUID(name);
- return new NameAndId(uuid, name);
+ return new NameAndId(uuid, name, false); // Leaves - fakeplayer
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 0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d..3a5319739f0687fc6f09b2ac8ee31716593fe0de 100644
index ebd2f2887780d9c6c3c44983bac23eab732cf43f..14be3d21cc1a613b1d9164ecc699073f0da2047c 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -317,6 +317,19 @@ public abstract class PlayerList {
@@ -319,6 +319,19 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
@@ -443,113 +465,114 @@ index 0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d..3a5319739f0687fc6f09b2ac8ee31716
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -791,6 +804,12 @@ public abstract class PlayerList {
@@ -791,6 +804,11 @@ public abstract class PlayerList {
respawnReason
).callEvent();
// Paper end
+ // 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
+ this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
+ }
+ // Leaves end - bot support
+
return serverPlayer;
}
@@ -892,11 +911,16 @@ public abstract class PlayerList {
return player;
}
@@ -893,11 +911,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
- 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
strings[i] = players.get(i).getGameProfile().name(); // Folia - region threading
names[i] = players.get(i).getGameProfile().name(); // 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().name();
+ 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 strings;
return names;
}
@@ -1016,7 +1040,14 @@ public abstract class PlayerList {
@@ -1016,8 +1039,15 @@ public abstract class PlayerList {
|| this.allowCommandsForAllPlayers;
}
public @Nullable ServerPlayer getPlayerByName(String username) {
- return this.playersByName.get(username.toLowerCase(java.util.Locale.ROOT)); // Spigot
- 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
+ username = username.toLowerCase(java.util.Locale.ROOT);
+ ServerPlayer player = this.playersByName.get(username);
+ name = name.toLowerCase(java.util.Locale.ROOT);
+ ServerPlayer player = this.playersByName.get(name);
+ if (player == null) {
+ player = this.server.getBotList().getBotByName(username);
+ player = this.server.getBotList().getBotByName(name);
+ }
+ 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) {
@@ -1353,7 +1384,13 @@ public abstract class PlayerList {
public void broadcast(
@@ -1360,7 +1390,13 @@ public abstract class PlayerList {
}
public @Nullable ServerPlayer getPlayer(UUID playerUUID) {
- return this.playersByUUID.get(playerUUID);
public @Nullable ServerPlayer getPlayer(final UUID uuid) {
- return this.playersByUUID.get(uuid);
+ // Leaves start - fakeplayer support
+ ServerPlayer player = this.playersByUUID.get(playerUUID);
+ ServerPlayer player = this.playersByUUID.get(uuid);
+ if (player == null) {
+ player = this.server.getBotList().getBot(playerUUID);
+ player = this.server.getBotList().getBot(uuid);
+ }
+ return player;
+ // Leaves start - fakeplayer support
}
public @Nullable ServerPlayer getPlayer(String name) {
public @Nullable ServerPlayer getPlayer(final String playerName) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 32299faedd89a848ca00288672ce85cad707dca0..3e44a61bd982dc822437f647a02a95affd988cdb 100644
index f090b8d77bd2731debfc61c263bd77550f52212b..03c155140da7300f6f934aff323e0daed1b63366 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1235,7 +1235,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -1257,7 +1257,7 @@ public abstract class Entity
BlockPos onPosLegacy = this.getOnPosLegacy();
BlockState blockState = this.level().getBlockState(onPosLegacy);
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(vec3.y, this.onGround(), blockState, onPosLegacy);
this.checkFallDamage(movement.y, this.onGround(), effectState, effectPos);
}
@@ -1570,7 +1570,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
@@ -1602,7 +1602,7 @@ public abstract class Entity
return colliders.isEmpty() ? maxDistance : -Shapes.collide(Direction.Axis.Y, aabb, colliders, -maxDistance);
}
// Paper start - optimise collisions
- private Vec3 collide(Vec3 movement) {
+ public Vec3 collide(Vec3 movement) { // Leaves - private -> public
- 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;
final boolean zZero = movement.z == 0.0;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 3fe9afe55b4d61db8030479d3d74b8656679cb10..c0ebd700caa950948c58846eaf164afc14f87f09 100644
index 2bce20202b7c539bee3685741663a8ed225919ff..a2f44e4354f6aa1c0502cba40cadaad59193b169 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3319,7 +3319,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);
@@ -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(player));
this.setSpeed(this.getRiddenSpeed(controller));
this.travel(riddenInput);
} else {
@@ -4228,7 +4228,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -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() && !usingItem.useOnRelease()) {
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide() && !usingItem.useOnRelease()) {
- 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();
@@ -4413,6 +4413,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -4459,6 +4459,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
this.stopUsingItem();
}
@@ -572,22 +595,22 @@ index 3fe9afe55b4d61db8030479d3d74b8656679cb10..c0ebd700caa950948c58846eaf164afc
+
public void stopUsingItem() {
if (!this.level().isClientSide()) {
boolean isUsingItem = this.isUsingItem();
boolean wasUsingItem = this.isUsingItem();
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 83612969b6058f444fc17e360cdcc4a8846f79aa..29ca31b05ec5636243b13fee8b3399d5e21808b4 100644
index b45481f781f3556001af89704b718d6291ba1f66..2135ea645131c27b9bec5534431199f9d55134d8 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -168,7 +168,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -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;
+ protected ItemStack lastItemInMainHand = ItemStack.EMPTY; // Leaves - fakeplayer
private final ItemCooldowns cooldowns = this.createItemCooldowns();
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
public @Nullable FishingHook fishing;
@@ -349,6 +349,12 @@ public abstract class Player extends Avatar implements ContainerUser {
}
@@ -340,6 +340,12 @@ public abstract class Player extends Avatar implements ContainerUser {
this.updatePlayerPose();
}
+ // Leaves start - fakeplayer
@@ -599,26 +622,26 @@ index 83612969b6058f444fc17e360cdcc4a8846f79aa..29ca31b05ec5636243b13fee8b3399d5
@Override
protected float getMaxHeadRotationRelativeToBody() {
return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody();
@@ -574,7 +580,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -565,7 +571,7 @@ public abstract class Player extends Avatar implements ContainerUser {
public void removeEntitiesOnShoulder() {
}
- private void touch(Entity entity) {
+ public void touch(Entity entity) { // Leaves - private -> public
- private void touch(final Entity entity) {
+ public void touch(final Entity entity) { // Leaves - private -> public
entity.playerTouch(this);
}
@@ -1251,7 +1257,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -1247,7 +1253,7 @@ public abstract class Player extends Avatar implements ContainerUser {
// Paper end - Configurable sprint interruption on attack
}
- if (target instanceof ServerPlayer && target.hurtMarked) {
+ if ((target instanceof ServerPlayer && !(target instanceof org.leavesmc.leaves.bot.ServerBot)) && target.hurtMarked) { // Leaves - bot knockback
- 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) target.getBukkitEntity();
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 71f6acc07d222fe512bf8d9fbaad35cb36bcf2d6..a9f5d503fbe50e54f2f44be2ca6d414430f4481e 100644
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 {
@@ -631,7 +654,7 @@ index 71f6acc07d222fe512bf8d9fbaad35cb36bcf2d6..a9f5d503fbe50e54f2f44be2ca6d4144
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 fc1b3501114108d0166256c514a225337955e461..56bc87fefc82c77077bfed50accbde778c0059ea 100644
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 {
@@ -661,23 +684,23 @@ index fc1b3501114108d0166256c514a225337955e461..56bc87fefc82c77077bfed50accbde77
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 e7ea8849e8fa942709f505145e8076f064476206..4935234fba5977246aa303bf8162404813b5491e 100644
index fa1f7dd22959632aaa54e72c8caf13ea072e7ca7..ae6056c3b6ae3eebdfb59cf54d7333dfc2cebf6a 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -404,6 +404,7 @@ public abstract class AbstractContainerMenu {
@@ -407,6 +407,7 @@ public abstract class AbstractContainerMenu {
private void doClick(int slotIndex, int button, ClickType clickType, Player player) {
private void doClick(final int slotIndex, final int buttonNum, final ContainerInput containerInput, final Player player) {
Inventory inventory = player.getInventory();
+ if (!doClickCheck(slotIndex, button, clickType, player)) return; // Leaves - doClick check
if (clickType == ClickType.QUICK_CRAFT) {
int i = this.quickcraftStatus;
this.quickcraftStatus = getQuickcraftHeader(button);
@@ -678,6 +679,22 @@ public abstract class AbstractContainerMenu {
+ 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 button, ClickType actionType, Player player) {
+ private boolean doClickCheck(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) {
+ if (slotIndex < 0) {
+ return true;
+ }
@@ -692,23 +715,23 @@ index e7ea8849e8fa942709f505145e8076f064476206..4935234fba5977246aa303bf81624048
+ }
+ // 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)
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 73a97f4f62fe7d27b441cab58c6c86ffce011060..ea6285b7f53f391c84519aa7ae39164cf5740b81 100644
index b052bc0107d93cd65a6c92914d6b3d02d6cc5ccb..fd2545f33692f964b62415178069e46e9c9d4c02 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -456,7 +456,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(serverLevel, player, hand, blocks.getFirst(), clickedPos);
@@ -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
interactionResult = InteractionResult.FAIL; // cancel placement
result = InteractionResult.FAIL; // cancel placement
// PAIL: Remove this when MC-99075 fixed
player.containerMenu.forceHeldSlot(hand);
@@ -987,6 +987,20 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -982,6 +982,20 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
}
}
@@ -730,44 +753,30 @@ index 73a97f4f62fe7d27b441cab58c6c86ffce011060..ea6285b7f53f391c84519aa7ae39164c
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 557ea70254a8d6dd87c656098c5632bdcbe3df8f..1d60054146f970ec24054d2c76a27e2d8620ec67 100644
index 282849162b88354893a15533e66d046fdd035bd6..2ecb10fe97d15954e44c61247eabc8818eb16f34 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 {
@@ -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 d1 = deltaMovement.x;
double d2 = deltaMovement.y;
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 e9c40ecb2309d386a2214593181f2d4f289eb28b..17dff8aed5015bfd22d021e2fcf536265d179139 100644
index 9d7238a28440ddc442c9288a617795261df767d9..142ab133d3b68eb9b88651e307653f1aafdf1de3 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);
@@ -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 (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;
}
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))
@@ -10,10 +10,10 @@ 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 f046aca874eb3376696baaad3719a6987afbfe22..268b2c6b981c8164fb829eb8a33beb213fe60bcf 100644
index 28776f3363810259f8c3bfdfd9f8c0455975be2a..0f562d7403aebf6c0907f2a33f758f4351ef282e 100644
--- a/net/minecraft/commands/CommandSourceStack.java
+++ b/net/minecraft/commands/CommandSourceStack.java
@@ -562,7 +562,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@@ -562,7 +562,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, ExecutionCo
@Override
public Collection<String> getOnlinePlayerNames() {
@@ -23,80 +23,80 @@ index f046aca874eb3376696baaad3719a6987afbfe22..268b2c6b981c8164fb829eb8a33beb21
@Override
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
index af71e0e1eb1c93745f3e4954ecc8fbd2ad4808a3..f3829564681faff3ae8971ed90b947b4a082a636 100644
index 7e3912b8b29e40eb3347f1451b0fd3ebee2af4f1..0834e402e6af7028e08851378e15390ec6314380 100644
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -126,11 +126,12 @@ public class EntitySelector {
return this.findPlayers(source);
@@ -142,11 +142,12 @@ public class EntitySelector {
return this.findPlayers(sender);
} else if (this.playerName != null) {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null ? List.of() : List.of(playerByName);
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 serverLevel : source.getServer().getAllLevels()) {
Entity entity = serverLevel.getEntity(this.entityUUID);
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(source.enabledFeatures())) {
if (entity.getType().isEnabled(sender.enabledFeatures())) {
return List.of(entity);
}
@@ -144,7 +145,7 @@ public class EntitySelector {
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
@@ -160,7 +161,7 @@ public class EntitySelector {
AABB absoluteAabb = this.getAbsoluteAabb(pos);
if (this.currentEntity) {
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
- return source.getEntity() != null && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of();
+ return source.getEntity() != null && !(source.getEntity() instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of(); // Leaves - skip photographer
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(vec3, absoluteAabb, source.enabledFeatures());
List<Entity> list = new ObjectArrayList<>();
@@ -155,6 +156,7 @@ public class EntitySelector {
this.addEntities(list, serverLevel1, absoluteAabb, predicate);
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);
}
}
+ list.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
+ result.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
return this.sortAndLimit(vec3, list);
return this.sortAndLimit(pos, result);
}
@@ -190,9 +192,11 @@ public class EntitySelector {
this.checkPermissions(source);
@@ -206,9 +208,11 @@ public class EntitySelector {
this.checkPermissions(sender);
if (this.playerName != null) {
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null ? List.of() : List.of(playerByName);
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 playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID);
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
return playerByName == null ? List.of() : List.of(playerByName);
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 vec3 = this.position.apply(source.getPosition());
@@ -204,11 +208,11 @@ public class EntitySelector {
int resultLimit = this.getResultLimit();
List<ServerPlayer> players;
Vec3 pos = this.position.apply(sender.getPosition());
@@ -220,11 +224,11 @@ public class EntitySelector {
int limit = this.getResultLimit();
List<ServerPlayer> result;
if (this.isWorldLimited()) {
- players = source.getLevel().getPlayers(predicate, resultLimit);
+ players = source.getLevel().getPlayers((player -> !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(player)), resultLimit); // Leaves - skip photographer
- 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 {
players = new ObjectArrayList<>();
result = new ObjectArrayList<>();
- for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) {
+ for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().realPlayers) { // Leaves - only real players
if (predicate.test(serverPlayer1)) {
players.add(serverPlayer1);
if (players.size() >= resultLimit) {
- 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 dfcf8eb7dc422a55d94d6eb9eb1451c7c14a1d56..9130f1fbf15500f2149418b73ae2a374bba22eee 100644
index c4685bb540e95d889dfbc107923876045be29848..f99c02b4d88cea924e20ca8dced67873c83c093f 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1896,7 +1896,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1930,7 +1930,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
+ 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());
@@ -2105,7 +2105,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2151,7 +2151,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public int getPlayerCount() {
@@ -105,40 +105,40 @@ index dfcf8eb7dc422a55d94d6eb9eb1451c7c14a1d56..9130f1fbf15500f2149418b73ae2a374
}
public String[] getPlayerNames() {
@@ -2309,7 +2309,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2363,7 +2363,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} else {
int i = 0;
int count = 0;
- for (ServerPlayer serverPlayer : this.getPlayerList().getPlayers()) {
+ for (ServerPlayer serverPlayer : this.getPlayerList().realPlayers) { // Leaves - only real players
serverPlayer.getBukkitEntity().taskScheduler.schedule((ServerPlayer player) -> { // Folia - region threading
- 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 = player.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null); // Folia - region threading
@@ -2494,7 +2494,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
@@ -2632,7 +2632,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
org.bukkit.event.player.PlayerGameModeChangeEvent event = updatedPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null); // Folia - region threading
@@ -2550,7 +2550,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
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
@@ -2686,7 +2686,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
PlayerList playerList = this.getPlayerList();
UserWhiteList whiteList = playerList.getWhiteList();
- for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) {
+ for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.realPlayers)) { // Leaves - only real player
if (!whiteList.isWhiteListed(serverPlayer.nameAndId()) && !this.getPlayerList().isOp(serverPlayer.nameAndId())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420)
serverPlayer.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
- 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 5bf7eb5b906cefa57a1dfcf828ff7872dbceac4f..85923708c32a0597e98e028eeec501f2ea07b63b 100644
index 89448eee9f135de8b406bf5f4147b3298e33ba17..b286aefc7d328bc7a7f44ce93615392075d9fef7 100644
--- a/net/minecraft/server/PlayerAdvancements.java
+++ b/net/minecraft/server/PlayerAdvancements.java
@@ -167,7 +167,7 @@ public class PlayerAdvancements {
@@ -169,7 +169,7 @@ public class PlayerAdvancements {
public boolean award(AdvancementHolder advancement, String criterionKey) {
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
@@ -146,33 +146,33 @@ index 5bf7eb5b906cefa57a1dfcf828ff7872dbceac4f..85923708c32a0597e98e028eeec501f2
}
// Leaves end - bot can't get advancement
diff --git a/net/minecraft/server/ServerScoreboard.java b/net/minecraft/server/ServerScoreboard.java
index 04a62e5ab9c0d0b9b7959280b0e0ea3ff388c017..e4260ec1938a43d41e007ad67a2b5be96a00227c 100644
index 9bf09b888425e491072864265c8de3885154a0ba..97a8fee8280061312a28013a5400e835db2eb474 100644
--- a/net/minecraft/server/ServerScoreboard.java
+++ b/net/minecraft/server/ServerScoreboard.java
@@ -249,7 +249,7 @@ public class ServerScoreboard extends Scoreboard {
public void startTrackingObjective(Objective objective) {
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
@@ -245,7 +245,7 @@ public class ServerScoreboard extends Scoreboard {
public void startTrackingObjective(final Objective objective) {
List<Packet<?>> packets = this.getStartTrackingPackets(objective);
- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
+ for (ServerPlayer serverPlayer : this.server.getPlayerList().realPlayers) { // Leaves - only real players
if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
for (Packet<?> packet : startTrackingPackets) {
serverPlayer.connection.send(packet);
@@ -275,7 +275,7 @@ public class ServerScoreboard extends Scoreboard {
public void stopTrackingObjective(Objective objective) {
List<Packet<?>> stopTrackingPackets = 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);
@@ -271,7 +271,7 @@ public class ServerScoreboard extends Scoreboard {
public void stopTrackingObjective(final Objective objective) {
List<Packet<?>> packets = this.getStopTrackingPackets(objective);
- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
+ for (ServerPlayer serverPlayer : this.server.getPlayerList().realPlayers) { // Leaves - only real players
if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
for (Packet<?> packet : stopTrackingPackets) {
serverPlayer.connection.send(packet);
- 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 e7c778a7f292fd0749cbd5e6586ad1b93ac7f29e..024b56405bb58801b17a6adad7fec7a461d12a5c 100644
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(CommandSourceStack source, Function<ServerPlayer, Component> nameExtractor) {
private static int format(final CommandSourceStack source, final Function<ServerPlayer, Component> formatter) {
PlayerList playerList = source.getServer().getPlayerList();
// CraftBukkit start
- List<ServerPlayer> playersTemp = playerList.getPlayers();
@@ -181,28 +181,29 @@ index e7c778a7f292fd0749cbd5e6586ad1b93ac7f29e..024b56405bb58801b17a6adad7fec7a4
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 590891d70a71ab30ceae3a3cf1923745e7c20b26..0ede1e5c73a0071e854de70f81ae1fc6a1d6dc59 100644
index 20cbc0e65fea3fc2d0033259c2f35e158ea81926..6bcd09b8d39333bd5f2c0d7c0a9a91bb52f9314d 100644
--- a/net/minecraft/server/commands/OpCommand.java
+++ b/net/minecraft/server/commands/OpCommand.java
@@ -25,7 +25,7 @@ public class OpCommand {
(commandContext, suggestionsBuilder) -> {
PlayerList playerList = commandContext.getSource().getServer().getPlayerList();
@@ -25,7 +25,8 @@ public class OpCommand {
(c, p) -> {
PlayerList list = c.getSource().getServer().getPlayerList();
return SharedSuggestionProvider.suggest(
- playerList.getPlayers()
+ playerList.realPlayers // Leaves - only real player
.stream()
.filter(serverPlayer -> !playerList.isOp(serverPlayer.nameAndId()))
.map(serverPlayer -> serverPlayer.getGameProfile().name()),
- 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 b5cb0fd45c1e33f40ff38e86772c9e6cc06c10a0..e9ac6ee47fd9c3d73e55a3467bb1c53f931609d0 100644
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,
- commandContext.getSource().getServer().getPlayerList().getPlayers()
+ commandContext.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
- c.getSource().getServer().getPlayerList().getPlayers()
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -210,136 +211,122 @@ index b5cb0fd45c1e33f40ff38e86772c9e6cc06c10a0..e9ac6ee47fd9c3d73e55a3467bb1c53f
0.0F,
0,
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
- c.getSource().getServer().getPlayerList().getPlayers()
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -68,7 +68,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
FloatArgumentType.getFloat(c, "speed"),
IntegerArgumentType.getInteger(c, "count"),
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
- c.getSource().getServer().getPlayerList().getPlayers()
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -82,7 +82,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
FloatArgumentType.getFloat(c, "speed"),
IntegerArgumentType.getInteger(c, "count"),
true,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
- c.getSource().getServer().getPlayerList().getPlayers()
+ c.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -112,7 +112,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
FloatArgumentType.getFloat(c, "speed"),
IntegerArgumentType.getInteger(c, "count"),
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
- 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 0ae4d68dfe42004839a0c5ad457de592f6b4af8b..1d1e396e4b29f33669872fb39e3a7f1d474a49f7 100644
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> list = commandSourceStack.getServer()
List<ServerPlayer> receivers = source.getServer()
.getPlayerList()
- .getPlayers()
+ .realPlayers // Leaves - only real players
.stream()
.filter(player -> player == entityOrException || player.getTeam() == team)
.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 305273583b3d2ad233c6cd67883baad15fe572eb..ce2939eac9c66e0c6eaac1570c4da19d908662ad 100644
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 {
(commandContext, suggestionsBuilder) -> {
PlayerList playerList = commandContext.getSource().getServer().getPlayerList();
(c, p) -> {
PlayerList list = c.getSource().getServer().getPlayerList();
return SharedSuggestionProvider.suggest(
- playerList.getPlayers()
+ playerList.realPlayers // Leaves - only real player
- list.getPlayers()
+ list.realPlayers // Leaves - only real player
.stream()
.map(Player::nameAndId)
.filter(nameAndId -> !playerList.getWhiteList().isWhiteListed(nameAndId))
.filter(nameAndId -> !list.getWhiteList().isWhiteListed(nameAndId))
diff --git a/net/minecraft/server/gui/PlayerListComponent.java b/net/minecraft/server/gui/PlayerListComponent.java
index 5a8cd3e6b448a4472092690cf589bca10b142126..158593b1a6384db635a1f224919b24c174944b10 100644
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> list = new Vector<>();
Vector<String> players = new Vector<>();
- for (int i = 0; i < this.server.getPlayerList().getPlayers().size(); i++) {
- list.add(this.server.getPlayerList().getPlayers().get(i).getGameProfile().name());
+ for (int i = 0; i < this.server.getPlayerList().realPlayers.size(); i++) {
+ list.add(this.server.getPlayerList().realPlayers.get(i).getGameProfile().name());
- 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(list);
this.setListData(players);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 14516c3ebd092e6f230804145a60dc851f34230b..bd33a381490ec3f03af9d22c9337f5d686014d85 100644
index 2ddcf6ae90aaaf98e2fcd8ab9995b6f0d7791856..a7cebb797973cde399dc30c696b064efd40874f2 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2972,7 +2972,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
@@ -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 (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
ServerLevel.this.realPlayers.add(serverPlayer);
- 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
@@ -3058,7 +3058,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
@@ -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 (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
ServerLevel.this.realPlayers.remove(serverPlayer);
- 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/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 3efce8ae3cba85019aea7453f97a72939baef7f6..0741dc695c0b22a6edd9a51a9dcdec0cdd545326 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -202,7 +202,7 @@ import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
- private static final Logger LOGGER = LogUtils.getLogger();
+ protected static final Logger LOGGER = LogUtils.getLogger();
public static final long LAST_SAVE_ABSENT = Long.MIN_VALUE; public long lastSave = LAST_SAVE_ABSENT; // Paper // Folia - threaded regions - changed to nanoTime
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
@@ -669,7 +669,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
// Paper start - Expand PlayerGameModeChangeEvent
this.loadGameTypes(input);
}
- private void loadGameTypes(ValueInput input) {
+ public void loadGameTypes(ValueInput input) { // Lophine - private -> public
if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != readPlayerMode(input, "playerGameType")) {
if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), org.bukkit.GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) {
this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE);
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f25ff5c0b 100644
index 14be3d21cc1a613b1d9164ecc699073f0da2047c..baa295f3dd8cf10bf7347ee4d1c249b1f82c9279 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -130,6 +130,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
+ public final List<ServerPlayer> realPlayers = new java.util.concurrent.CopyOnWriteArrayList<>(); // Leaves - replay api
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -218,6 +219,123 @@ public abstract class PlayerList {
@@ -191,6 +192,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;
@@ -221,6 +223,124 @@ public abstract class PlayerList {
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
@@ -352,18 +339,17 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+
+ player.setServerLevel(worldserver1);
+ player.spawnIn(worldserver1);
+ player.gameMode.setLevel((ServerLevel) player.level());
+ player.gameMode.setLevel(player.level());
+
+ LevelData worlddata = worldserver1.getLevelData();
+
+ //player.loadGameTypes(null); // simply fix for https://github.com/MC-XiaoHei/ISeeYou/issues/70
+ 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(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1), this.server.enforceSecureProfile())); // Paper - replace old player chunk management
+ 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()));
@@ -389,7 +375,6 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+ this.playersByUUID.put(player.getUUID(), player);
+
+ player.suppressTrackerForLogin = true;
+ worldserver1.getCurrentWorldData().connections.add(player.connection.connection);
+ worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
@@ -415,19 +400,20 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+ // Leaves end - bot support
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
+ final List<ServerPlayer> playerList = List.copyOf(this.players); // Lophine - copy to avoid ConcurrentModificationException
+ for (ServerPlayer serverPlayer : playerList) {
+ if (serverPlayer == player || !bukkitPlayer.canSee(serverPlayer.getBukkitEntity())) {
+ 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 (serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
+ if (entityplayer1 instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
+ continue;
+ }
+ // Leaves end - skip photographer
+
+ onlinePlayers.add(serverPlayer);
+ onlinePlayers.add(entityplayer1);
+ }
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
@@ -435,7 +421,7 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+
+ player.sentListPacket = true;
+ player.suppressTrackerForLogin = false;
+ player.level().getChunkSource().chunkMap.addEntity(player);
+ ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player);
+
+ this.sendLevelInfo(player, worldserver1);
+
@@ -445,7 +431,9 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+ }
+
+ worldserver1 = player.level();
+ for (MobEffectInstance mobeffect : player.getActiveEffects()) {
+ 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));
+ }
+
@@ -460,10 +448,10 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+ }
+ // Leaves end - replay mod api
+
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
public void placeNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -292,6 +410,7 @@ public abstract class PlayerList {
@@ -294,6 +414,7 @@ public abstract class PlayerList {
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
@@ -471,15 +459,15 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
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
@@ -507,6 +626,7 @@ public abstract class PlayerList {
@@ -513,6 +634,7 @@ public abstract class PlayerList {
}
protected void save(ServerPlayer player) {
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);
@@ -521,6 +641,44 @@ public abstract class PlayerList {
@@ -527,6 +649,47 @@ public abstract class PlayerList {
}
}
@@ -503,12 +491,15 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+ }
+ }
+
+ worldserver.getCurrentWorldData().connections.remove(entityplayer.connection.connection);
+ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
+ entityplayer.retireScheduler();
+ entityplayer.getAdvancements().stopListening();
+ this.players.remove(entityplayer);
+ this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT));
+ // 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);
@@ -519,12 +510,12 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
+
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
+ }
+ // Leaves stop - replay mod api
+ // Leaves end - replay mod api
+
public net.kyori.adventure.text.@Nullable Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
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())));
@@ -595,6 +753,7 @@ public abstract class PlayerList {
@@ -600,6 +763,7 @@ public abstract class PlayerList {
player.getBukkitEntity().packetProcessor.close(); // Folia - region threading
player.getAdvancements().stopListening();
this.players.remove(player);
@@ -532,31 +523,33 @@ index 36cd1a0307ff1a734eb5f4f3cc013781692e7ad8..0c3e6c1f70289c63bfe424a49374602f
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
this.server.getCustomBossEvents().onPlayerDisconnect(player);
UUID uuid = player.getUUID();
@@ -910,15 +1069,15 @@ public abstract class PlayerList {
@@ -910,15 +1074,15 @@ 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() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
+ List<ServerPlayer> players = new java.util.ArrayList<>(this.realPlayers); // Folia - region threading
+ String[] strings = new String[players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support, and skip photographer
- 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
strings[i] = players.get(i).getGameProfile().name(); // Folia - region threading
- 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 < strings.length; ++i) {
- strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().name();
+ for (int i = players.size(); i < strings.length; ++i) { // Leaves - only real players
+ strings[i] = this.server.getBotList().bots.get(i - players.size()).getGameProfile().name(); // Leaves - only real players
- 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 c0ebd700caa950948c58846eaf164afc14f87f09..e4ae4354e81f34f0db410333fc9b8e17383a5f41 100644
index a2f44e4354f6aa1c0502cba40cadaad59193b169..a3c19d725e03c07de6708f3c2d092e0b9aea69c2 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -262,7 +262,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -261,7 +261,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
public int useItemRemaining;
protected int fallFlyTicks;
private long lastKineticHitFeedbackTime = -2147483648L;
@@ -1,243 +0,0 @@
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 9130f1fbf15500f2149418b73ae2a374bba22eee..eef40103bcec3b836ffb50154fb05926b9757723 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1975,11 +1975,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 bd33a381490ec3f03af9d22c9337f5d686014d85..284bd9703b11804f51273ecfaa5cd44925726f5f 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 0741dc695c0b22a6edd9a51a9dcdec0cdd545326..3fc09529159d202ce6201626be535d791818fa4a 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 3e44a61bd982dc822437f647a02a95affd988cdb..28ae21b08e42edcc031ace2404b9d213589c28e8 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,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 2135ea645131c27b9bec5534431199f9d55134d8..5e7e99410c7597ec5330cc82e441fa30c53c9532 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.carpet.config.modules.GeneralCompatConfig.creativeNoClip && isCreative() && getAbilities().flying);
+ }
+
+ public boolean canSpectatingPlace(final net.minecraft.world.level.LevelReader world, final BlockState state, final BlockPos pos, final net.minecraft.world.phys.shapes.CollisionContext context) {
+ 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..07b84bd0144e133d13e8e033a8998f3cf674f746 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -158,8 +158,9 @@ public class BlockItem extends Item {
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.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, stateForPlacement, context.getClickedPos(), collisionContext) : world.checkEntityCollision(stateForPlacement, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip
org.bukkit.entity.Player bukkitPlayer = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
index cb0a4a9865df69e5504a86de6c144bc4450bd19a..596fb91fccb4c8d6854fa859f9ee357c6d22a81e 100644
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
@@ -44,7 +44,7 @@ public class StandingAndWallBlockItem extends BlockItem {
// 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.carpet.config.modules.GeneralCompatConfig.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(level, stateForPlacement, pos, CollisionContext.empty()) : level.isUnobstructed(stateForPlacement, pos, CollisionContext.empty()); // Leaves - creative no clip
org.bukkit.entity.Player player = (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer serverPlayer) ? serverPlayer.getBukkitEntity() : null;
org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), pos), player, stateForPlacement.asBlockData(), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
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()));
@@ -1,24 +0,0 @@
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);
@@ -10,20 +10,20 @@ 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 6a51bace3151646afae9de820d9c8977a0221df4..474ca0ce0d3095fc586f8f9e9a584ed4f7c91471 100644
index d036018ee64995ee754296014888ee70c0ea5ab3..aa782c6441cdce3eb39aefb28d40f3b1970d4e62 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -229,8 +229,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
@@ -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, blockEntity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
+ 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++) {
+ flag |= suckInItems(level, blockEntity);
+ if (!flag) {
+ changed |= suckInItems(level, entity);
+ if (!changed) {
+ break;
+ } else {
+ woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos));
@@ -33,32 +33,32 @@ index 6a51bace3151646afae9de820d9c8977a0221df4..474ca0ce0d3095fc586f8f9e9a584ed4
+ }
+ // Leaves end - Wool hopper counter
+
if (flag) {
blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
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))) {
+ blockEntity.setCooldown(0);
+ 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
@@ -462,6 +484,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -491,6 +513,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
// Paper end - Perf: Optimize Hoppers
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
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, pos, level.getBlockState(pos), HopperBlockEntity.getContainerAt(level, pos))) {
+ if (woolHopperCounter(level, blockPos, level.getBlockState(blockPos), HopperBlockEntity.getContainerAt(level, blockPos))) {
+ return true;
+ }
+ }
+ // Leaves end - hopper counter
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
if (attachedContainer == null) {
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;
@@ -537,6 +566,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -512,6 +541,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
@@ -82,14 +82,14 @@ index 6a51bace3151646afae9de820d9c8977a0221df4..474ca0ce0d3095fc586f8f9e9a584ed4
+ }
+ // Leaves end - hopper counter
+
private static int[] getSlots(Container container, Direction direction) {
private static int[] getSlots(final Container container, final Direction direction) {
if (container instanceof WorldlyContainer worldlyContainer) {
return worldlyContainer.getSlotsForFace(direction);
@@ -681,6 +730,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -606,6 +655,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static boolean addItem(Container container, ItemEntity item) {
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && item.isRemoved()) return false; // Leaves - Wool hopper counter
boolean flag = false;
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 a7cebb797973cde399dc30c696b064efd40874f2..c0e62a69bb5c9e777265b5474d76ba8d06ccec4b 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..9b8ee2df5a0b6d76d9bfc747187f6cd51bb4a520 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 - fix some bug if player is cross scheduler >> to remove monster if the region don't have any valid player
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,
@@ -1,55 +0,0 @@
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,237 @@
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 24f5b890b0126fc817863f99b676da1a548f7608..a25bc31c04778bf12e3b6301ffcfb2275fcc2d90 100644
--- a/net/minecraft/network/PacketProcessor.java
+++ b/net/minecraft/network/PacketProcessor.java
@@ -106,7 +106,23 @@ public class PacketProcessor implements AutoCloseable {
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(ListenerAndPacket.this.packet.getClass().getName())); try { // Folia - profiler
this.packet.handle(this.listener);
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ // Lophine end - catch update suppression crash
} catch (Exception var3) {
+ // Lophine start - catch update suppression crash
+ if (var3.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ }
+
+ // Lophine end - catch update suppression crash
if (var3 instanceof ReportedException re && re.getCause() instanceof OutOfMemoryError) {
throw PacketUtils.makeReportedException(var3, this.packet, this.listener);
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f99c02b4d88cea924e20ca8dced67873c83c093f..0c042c4af5d52c08e9fbc03a04c4b696d8a0a7ed 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2019,11 +2019,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler
level.tick(haveTime, region); // Folia - region threading
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(level);
+ exception.consume();
+ // Lophine end - catch update suppression crash
} finally { foliaProfiler.stopTimer(level.tickTimerId); } // Folia - profiler
} catch (Throwable var7) {
- CrashReport report = CrashReport.forThrowable(var7, "Exception ticking world");
- level.fillReportDetails(report);
- throw new ReportedException(report);
+ // Lophine start - catch update suppression crash
+ org.leavesmc.leaves.util.UpdateSuppressionException updateSuppressionException = null;
+ if (var7 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ updateSuppressionException = exception;
+ } else if (var7.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ updateSuppressionException = exception;
+ }
+
+ if (updateSuppressionException != null) {
+ updateSuppressionException.provideLevel(level);
+ updateSuppressionException.consume();
+ } else {
+ CrashReport report = CrashReport.forThrowable(var7, "Exception ticking world");
+ level.fillReportDetails(report);
+ throw new ReportedException(report);
+ }
+ // Lophine end - catch update suppression crash
}
profiler.pop();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index c0e62a69bb5c9e777265b5474d76ba8d06ccec4b..3e7420cd98504732db17cb6b0fcfdfbb8deeb552 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -967,7 +967,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
// Kaiiju end
profiler.push("tick");
- this.guardEntityTick(this::tickNonPassenger, entity);
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ try {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(this);
+ exception.consume();
+ }
+ } else {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ }
+ // Lophine end - catch update suppression crash
profiler.pop();
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index cdb4a52cbd34322903144364c3686a4e1bf0fbb8..3a3a335a7659ebe946221186b56150df4a89c004 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1130,6 +1130,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
// Folia - region threading - move to main tick loop where we can detect duplicates
// CraftBukkit end
+ // Lophine start - catch update suppression crash
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.providePlayer(this);
+ exception.provideLevel(this.level());
+ exception.consume();
+ // Lophine end - catch update suppression crash
} catch (Throwable var4) {
CrashReport report = CrashReport.forThrowable(var4, "Ticking player");
CrashReportCategory category = report.addCategory("Player being ticked");
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 03c155140da7300f6f934aff323e0daed1b63366..ee84484ca5aac03b9f321398c4d85311632b5697 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1459,7 +1459,17 @@ public abstract class Entity
}
if (shouldVibrate) {
- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, blockState));
+ // Lophine start - catch update suppression crash
+ try {
+ this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, blockState));
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(level, pos, blockState.getBlock());
+ if (this instanceof net.minecraft.server.level.ServerPlayer player) {
+ exception.providePlayer(player);
+ }
+ exception.consume();
+ }
+ // Lophine end - catch update suppression crash
}
return true;
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 08ad9f418fbe733b788ec27e13b61994c3a5f09d..f9dacc278200b05acb385e1f1cbf858e43d0d9f4 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -181,7 +181,16 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@Override
protected int getAnalogOutputSignal(final BlockState state, final Level level, final BlockPos pos, final Direction direction) {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine start - catch update suppression crash
+ try {
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ } catch (ClassCastException ex) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
+ }
+ throw ex;
+ }
+ // Lophine end - catch update suppression crash
}
public @Nullable DyeColor getColor() {
diff --git a/net/minecraft/world/level/block/state/StateHolder.java b/net/minecraft/world/level/block/state/StateHolder.java
index b72861c0164ebb13b6fc3e78cd7ce0a2c484f22d..5bf43973c8de8c2f33d384f28fdd06864cdf9319 100644
--- a/net/minecraft/world/level/block/state/StateHolder.java
+++ b/net/minecraft/world/level/block/state/StateHolder.java
@@ -118,7 +118,16 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
if (ret != null) {
return ret;
}
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ // Lophine start - catch update suppression crash
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ org.leavesmc.leaves.util.UpdateSuppressionException exception = new org.leavesmc.leaves.util.UpdateSuppressionException(null, null, null, null, iae);
+ if (exception.getStackTrace()[1].getClassName().startsWith("net.minecraft")) {
+ throw exception;
+ }
+ }
+ throw iae;
+ // Lophine end - catch update suppression crash
// Paper end - optimise blockstate property access
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 3708f9ffc46a5b1c038c0e7b2ce84802e2b22397..241c43170b5020c1521f43d349813586ba1f69a5 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -400,6 +400,8 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
return null;
} else {
Block newBlock = state.getBlock();
+ // Lophine start - catch update suppression crash
+ try {
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(localX, y, localZ, state);
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(localX, y, localZ, state);
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(localX, y, localZ, state);
@@ -468,6 +470,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
this.markUnsaved();
return oldState;
}
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(this.level, pos, newBlock);
+ throw exception;
+ }
+ // Lophine end - catch update suppression crash
}
}
}
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
index 9b8d63f69ed1101f1b7b2728690e35165b9aeb99..6358787f3c7dcfa599b2949613236fa8de025096 100644
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
@@ -87,9 +87,24 @@ public interface NeighborUpdater {
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Spigot start
} catch (StackOverflowError ex) {
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, changedBlock, null, ex);
+ }
+ // Lophine end - catch update suppression crash
level.lastPhysicsProblem = pos.immutable();
// Spigot end
} catch (Throwable var9) {
+ // Lophine start - catch update suppression crash
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(level, pos, changedBlock);
+ throw exception;
+ }
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, changedBlock, null, var9);
+ }
+
+ // Lophine end - catch update suppression crash
CrashReport report = CrashReport.forThrowable(var9, "Exception while updating neighbours");
CrashReportCategory category = report.addCategory("Block being updated");
category.setDetail(
@@ -0,0 +1,26 @@
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 f9dacc278200b05acb385e1f1cbf858e43d0d9f4..722ce78461b2303f99493c309345697cfc98fb99 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -183,7 +183,11 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
protected int getAnalogOutputSignal(final BlockState state, final Level level, final BlockPos pos, final Direction direction) {
// Lophine start - catch update suppression crash
try {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine start - configurable shulker CCE
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.shulkerBoxCCEReintroduced
+ ? AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container)level.getBlockEntity(pos))
+ : AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Lophine end - configurable shulker CCE
} catch (ClassCastException ex) {
if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.mergedUpdateSuppressionCrashEnabled()) {
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
@@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Wed, 14 Jun 2023 12:07:07 +0800
Subject: [PATCH] Leaves: Redstone ignore upwards update
(Carpet: dustTrapdoorReintroduced)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
index 45e11737bc2558a4ebfffe133d43111f45dd7d16..db80f0b400c7356c5524ea799354e6c44de14700 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -59,6 +59,11 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ // Lophine start - redstone ignore upwards update
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
+ // Lophine end - redstone ignore upwards update
return directionToNeighbour == Direction.DOWN && !this.canSurviveOn(level, neighbourPos, neighbourState)
? Blocks.AIR.defaultBlockState()
: super.updateShape(state, level, ticks, pos, directionToNeighbour, neighbourPos, neighbourState, random);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 759eb347299813c20226cc2fc5dc7718d12b7f56..30a7208a698a8bd3ba8a08ace6f23b206d90f6a3 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -179,7 +179,11 @@ public class RedStoneWireBlock extends Block {
final RandomSource random
) {
if (directionToNeighbour == Direction.DOWN) {
- return !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
+ // Lophine start - redstone ignore upwards update
+ return fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced
+ ? state
+ : !this.canSurviveOn(level, neighbourPos, neighbourState) ? Blocks.AIR.defaultBlockState() : state;
+ // Lophine end - redstone ignore upwards update
} else if (directionToNeighbour == Direction.UP) {
return this.getConnectionState(level, state, pos);
} else {
@@ -243,7 +247,10 @@ public class RedStoneWireBlock extends Block {
BlockPos relativePos = pos.relative(direction);
BlockState relativeState = level.getBlockState(relativePos);
if (canConnectUp) {
- boolean isPlaceableAbove = relativeState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, relativePos, relativeState);
+ // Lophine start - redstone ignore upwards update
+ boolean isPlaceableAbove = (!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && relativeState.getBlock() instanceof TrapDoorBlock)
+ || this.canSurviveOn(level, relativePos, relativeState);
+ // Lophine end - redstone ignore upwards update
if (isPlaceableAbove && shouldConnectTo(level.getBlockState(relativePos.above()))) {
if (relativeState.isFaceSturdy(level, relativePos, direction.getOpposite())) {
return RedstoneSide.UP;
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
index d301ca4c91e75d715998aa7ed155fd44ccd64785..1985602b11a584fc70b1bb9ca4c643757d4c0ed3 100644
--- a/net/minecraft/world/level/block/RepeaterBlock.java
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
@@ -70,6 +70,11 @@ public class RepeaterBlock extends DiodeBlock {
final BlockState neighbourState,
final RandomSource random
) {
+ // Lophine start - redstone ignore upwards update
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.dustTrapdoorReintroduced && directionToNeighbour == Direction.DOWN) {
+ return state;
+ }
+ // Lophine end - redstone ignore upwards update
if (directionToNeighbour == Direction.DOWN && !this.canSurviveOn(level, neighbourPos, neighbourState)) {
return Blocks.AIR.defaultBlockState();
} else {
@@ -5,48 +5,60 @@ Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index c7f578c117baccb10c0c15b05a6c04e073f15da8..aee3f98173de1b2c5a5278919a5d21b4bca03b7b 100644
index 64d407c5a6140a7e5dc47a8e304b4c00602e2bdd..9911c70d89cfb43b803cab9bbe6eedd1142f59d6 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -472,7 +472,7 @@ public final class RegionizedWorldData {
@@ -506,7 +506,7 @@ public final class RegionizedWorldData {
public long lastMidTickExecuteFailure;
// From Level
public boolean populating;
- public final CollectingNeighborUpdater neighborUpdater;
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater;
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater; // Lophine - Instant Block Updater
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public final Map<BlockPos, CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
@@ -531,7 +531,7 @@ public final class RegionizedWorldData {
@@ -567,7 +567,11 @@ 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
+ // Lophine start - Instant Block Updater
+ this.neighborUpdater = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.instantBlockUpdaterReintroduced
+ ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world)
+ : new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
+ // Lophine end - Instant Block Updater
this.nearbyPlayers = new NearbyPlayers(world);
this.wireHandler = new alternate.current.wire.WireHandler(world);
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
@@ -896,4 +900,4 @@ public final class RegionizedWorldData {
public int getChunkCount() {
return this.chunks.size();
}
-}
\ No newline at end of file
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 284bd9703b11804f51273ecfaa5cd44925726f5f..9756caff0b7403c212987e58c08a2da09bdeb962 100644
index 3e7420cd98504732db17cb6b0fcfdfbb8deeb552..257b440a0eea379433e9a249175c8eb16c37accb 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
@@ -1001,11 +1001,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
// 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)) {
profiler.pop();
profiler.push("debugSynchronizers");
- 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 {
- } else {
- regionizedWorldData.neighborUpdater.setDebugListener(null); // Folia - region threading
+ neighborUpdater.setDebugListener(null); // Folia - region threading
+ // Lophine start - Instant Block Updater
+ if (regionizedWorldData.neighborUpdater instanceof net.minecraft.world.level.redstone.CollectingNeighborUpdater neighborUpdater) {
+ if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) {
+ neighborUpdater // Folia - region threading
+ .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
+ } else {
+ neighborUpdater.setDebugListener(null); // Folia - region threading
+ }
+ // Lophine end - Instant Block Updater
}
+ }
+ // Lophine end - instant neighbor updates
this.debugSynchronizers.tick(this.server.debugSubscribers());
profilerFiller.pop();
@@ -1,70 +0,0 @@
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
}
}
}
@@ -5,35 +5,29 @@ 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
index cfc8b668980e0cba74b3f0d42c4902eb6aa8b01e..f01894c230b1ae4add3e20329e8dc87571d2c793 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
@@ -133,31 +133,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;
boolean signal = level.hasNeighborSignal(pos);
if (signal != state.getValue(POWERED)) {
- // Paper start - Call BlockRedstoneEvent
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBinaryRedstoneChange(level, pos, signal)) {
- return;
- }
- // CraftBukkit end
- // Paper end - Call BlockRedstoneEvent
- // Paper start - break redstone on trapdoors early
- boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
- boolean open = state.getValue(TrapDoorBlock.OPEN) != signal;
- // 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
- if (signal && 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));
- Block.popResource(level, abovePos, new 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
@@ -43,7 +37,7 @@ index b45ae50db32c4156b8f8008335673d20c570c72d..af78831441f362b0129aa864854ce5a6
- }
- 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);
+ if (state.getValue(OPEN) != signal) { // Lophine - revert Paper trapdoor redstone handling
state = state.setValue(OPEN, signal);
this.playSound(null, level, pos, signal);
}
@@ -1,136 +0,0 @@
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 aee3f98173de1b2c5a5278919a5d21b4bca03b7b..24a8ea9a709ed9637a8e3814c6f8fe9f9f9dedff 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -525,6 +525,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) {
@@ -537,6 +540,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 f4c9c551fc39bae38e283ccbbc3cd116f0536a64..db13211b24208d8addd3c210155bc244b58f3942 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -506,6 +506,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
this.chunkMap.tick(hasTimeLeft);
profilerFiller.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() {
@@ -570,7 +589,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
}
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
} else {
+ // Lophine start - Global Entities Counter
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
+ spawnState = fun.bm.lophine.utils.EntitiesCounterUtil.runRemainingTasks(level, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
+ } else {
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, 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
@@ -578,7 +603,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
boolean flag = this.level.getGameRules().get(GameRules.SPAWN_MOBS) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threading
int i = this.level.getGameRules().get(GameRules.RANDOM_TICK_SPEED);
List<MobCategory> filteredSpawningCategories;
- if (flag && (this.spawnEnemies || this.spawnFriendlies)) { // Paper
+ if (spawnState != null && flag && (this.spawnEnemies || this.spawnFriendlies)) { // Paper // Lophine - Global Entities Counter
// Paper start - PlayerNaturallySpawnCreaturesEvent
for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading
int chunkRange = Math.min(level.spigotConfig.mobSpawnRange, entityPlayer.getBukkitEntity().getViewDistance());
@@ -636,7 +661,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
this.level.tickThunder(chunk);
}
- if (!spawnCategories.isEmpty()) {
+ if (spawnState != null && !spawnCategories.isEmpty()) { // Lophine - Global Entities Counter
if (this.level.getWorldBorder().isWithinBounds(pos)) { // Paper - rewrite chunk system
NaturalSpawner.spawnForChunk(this.level, chunk, spawnState, spawnCategories);
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 9756caff0b7403c212987e58c08a2da09bdeb962..4acd4718628b160c482b04da6ba905687b61bbad 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -765,6 +765,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
public void tick(BooleanSupplier hasTimeLeft, 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 profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
ProfilerFiller profilerFiller = Profiler.get();
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 91f0fbd75bc93355dc872390d91af83c76dc1dce..e7223540a7cef20b661bdb857ffba962d0f5d348 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -116,7 +116,7 @@ public final class NaturalSpawner {
return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator);
}
- static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) {
+ public static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { // Lophine - protected -> public
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
}
@@ -585,7 +585,7 @@ public final class NaturalSpawner {
private @Nullable EntityType<?> lastCheckedType;
private double lastCharge;
- SpawnState(
+ public SpawnState( // Lophine - protected -> public
int spawnableChunkCount,
Object2IntOpenHashMap<MobCategory> mobCategoryCounts,
PotentialCalculator spawnPotential,
@@ -9,34 +9,38 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index 3301e521a79adbc6dd76be05e69cce1c97f8697e..8dc1db0e6bafba19e07a7fa78f3920d572d38466 100644
index e1de10e1a0ec221a1109a03d86fddf47b1c06a5f..71cc37515c268abd698896d514b66cb49859691c 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -386,7 +386,18 @@ public class ServerPlayerGameMode {
@@ -392,7 +392,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;
BlockState adjustedState = block.playerWillDestroy(this.level, pos, state, this.player);
- boolean changed = this.level.removeBlock(pos, false);
+ // Lophine start - preserve drops before update suppression
+ boolean changed;
+ org.leavesmc.leaves.util.UpdateSuppressionException updateSuppressionException = null;
+ try {
+ 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;
+ changed = this.level.removeBlock(pos, false);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ updateSuppressionException = exception;
+ updateSuppressionException.provideBlock(this.level, pos, block);
+ updateSuppressionException.providePlayer(this.player);
+ changed = false;
+ }
+ // Leaves end - Prevent loss of item drops due to update suppression when breaking blocks
+ // Lophine end - preserve drops before update suppression
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("server broke {} {} -> {}", pos, blockState1, this.level.getBlockState(pos));
LOGGER.info("server broke {} {} -> {}", pos, adjustedState, this.level.getBlockState(pos));
}
@@ -418,6 +429,7 @@ public class ServerPlayerGameMode {
@@ -424,6 +435,11 @@ 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
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, bState, 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
+ // Lophine start - preserve drops before update suppression
+ if (updateSuppressionException != null) {
+ throw updateSuppressionException;
+ }
+ // Lophine end - preserve drops before update suppression
// Drop event experience
if (flag) {
if (changed) {
@@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 17 Dec 2025 00:20:57 +0800
Subject: [PATCH] Add null check in RegionizedWorldData >> conections
some of our function patches will crash because of get null in conn.getPlayer(), then when we process player.chunkPosition() will get NPE, so we need to fix it.
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index 24a8ea9a709ed9637a8e3814c6f8fe9f9f9dedff..35f8bcb5569987e4096ea06bab4e6693dfb97695 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -229,14 +229,17 @@ public final class RegionizedWorldData {
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift)).itemEntityMovementTrackerMap.put(key, tracker);
}
// Luminol end
+ Set<Connection> cons = new java.util.HashSet<>(from.connections.size()); // Lophine - save all connections we have processed in connection process
// connections
for (final Connection conn : from.connections) {
final ServerPlayer player = conn.getPlayer();
+ if (player == null) continue; // Lophine - skip null player connections
final ChunkPos pos = player.chunkPosition();
// Note: It is impossible for an entity in the world to _not_ be in an entity chunk, which means
// the chunk holder must _exist_, and so the region section exists.
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
.connections.add(conn);
+ cons.add(conn); // Lophine - save all connections we have processed in connection process
}
// entities
for (final ServerPlayer player : from.localPlayers) {
@@ -247,6 +250,13 @@ public final class RegionizedWorldData {
into.localPlayers.add(player);
player.getBukkitEntity().updateRegion(into);
into.nearbyPlayers.addPlayer(player);
+ // Lophine start - we need to process the connection if player's connection is not processed, if connection.player is null, next tick will clean up it
+ final Connection conn = player.connection.connection;
+ if (!cons.contains(conn)) {
+ regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
+ .connections.add(conn);
+ }
+ // Lophine end
}
for (final Entity entity : from.allEntities) {
final ChunkPos pos = entity.chunkPosition();
@@ -585,6 +595,7 @@ public final class RegionizedWorldData {
private static void cleanUpConnection(final Connection conn) {
// note: ALL connections HERE have a player
final ServerPlayer player = conn.getPlayer();
+ if (player == null) return; // Lophine - skip null player connections
// now that the connection is removed, we can allow this region to die
player.level().moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(
ServerGamePacketListenerImpl.DISCONNECT_TICKET, player.connection.disconnectPos,
@@ -0,0 +1,52 @@
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 07b84bd0144e133d13e8e033a8998f3cf674f746..9c016e7d93e4c44ddf2df520e5c57d92a0e085b3 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -69,20 +69,8 @@ public class BlockItem extends Item {
BlockState placedState = level.getBlockState(pos);
if (placedState.is(placementState.getBlock())) {
placedState = this.updateBlockStateFromTag(pos, level, itemStack, placedState);
- // Paper start - Reset placed block on exception
- try {
this.updateCustomBlockEntityTag(pos, level, player, itemStack, placedState);
updateBlockEntityComponents(level, pos, itemStack);
- } catch (Exception ex) {
- ((org.bukkit.craftbukkit.block.CraftBlockState) previousState).revertPlace();
- if (player instanceof ServerPlayer serverPlayer) {
- net.minecraft.server.MinecraftServer.LOGGER.warn("Player {} tried placing invalid block", player.getScoreboardName(), ex);
- serverPlayer.connection.disconnect(net.minecraft.network.chat.Component.literal("Packet processing error"));
- return InteractionResult.FAIL;
- }
- throw ex; // Rethrow exception if not placed by a player
- }
- // Paper end - Reset placed block on exception
placedState.getBlock().setPlacedBy(level, pos, placedState, player, itemStack);
// CraftBukkit start - special case for handling block placement with water lilies, frog spawn and snow buckets
if (player != null && (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem)) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 241c43170b5020c1521f43d349813586ba1f69a5..316b8d45b0902b1bf01a77307e24fc9a47d1283b 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1017,12 +1017,6 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
profiler.pop();
} catch (Throwable var5) {
- // Paper start - Prevent block entity and entity crashes
- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", io.papermc.paper.util.MCUtil.getLevelName(LevelChunk.this.getLevel()), 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
}
}
}
@@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 13 Jan 2026 21:04:59 +0800
Subject: [PATCH] Add removed check before all checks start in addEffect
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index e4ae4354e81f34f0db410333fc9b8e17383a5f41..fc8833655102ca98bb331782a624af79cbef414f 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1186,6 +1186,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
// Paper end - Don't fire sync event during generation
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
+ if (this.isRemoved()) return false; // Lophine - shouldn't be possible to add effects to removed entity
if (!this.hasNullCallback()) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add effects to entities asynchronously"); // Folia - region threading
if (this.isTickingEffects) {
this.effectsToProcess.add(new ProcessableEffect(effectInstance, cause));
@@ -8,14 +8,15 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java
index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644
index 1311d4936f84652c5ffc51544f99cb98fc293906..3a62831838a60776159dcb1ca783d3f00e6cd35e 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) {
@@ -51,4 +51,16 @@ public class Containers {
public static void updateNeighboursAfterDestroy(final BlockState state, final Level level, final BlockPos pos) {
level.updateNeighbourForOutputSignal(pos, state.getBlock());
}
+
+
+ // Leaves start - behaviour 1.21.1-
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
+ if (!state.is(newState.getBlock())) {
@@ -28,10 +29,10 @@ index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab
+ // 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
index 98561dcc465ca9d5394e58b05ad3e8dc59773ebc..72e3d6c1ce3389972df21d5ff6e4d74bcf2ad300 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 {
@@ -53,6 +53,27 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
@@ -54,15 +55,16 @@ index dcc1bb4fcee9646212a424c03f77370ffa577fee..ca5cf7526082b9d3a7887dd77313e2c0
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
index 8139799a24274cfb70a99d301c2688c0360720c6..b224d3756120cd82d1381c55a95ad63c18c123b7 100644
index 5332fd32fa7a0d3fc3be1b0a7c2ca5dee8e402c6..37667a8e512bdba385c563e950d8c5d5cdd18832 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 {
@@ -51,6 +51,15 @@ public class BarrelBlock extends BaseEntityBlock {
return InteractionResult.SUCCESS;
}
@@ -73,15 +75,16 @@ index 8139799a24274cfb70a99d301c2688c0360720c6..b224d3756120cd82d1381c55a95ad63c
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
index 7135a6bc87f90fafa94d0783aaf7b42d66449010..afd06de092a75c6c4f7b8848055e314b0c241029 100644
index c2fbf44e93e44c36423465d406b5e4d3db029a80..a28a453f139295834c77aa908027c74c8dfd7aba 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 {
@@ -133,6 +133,20 @@ public abstract class BasePressurePlateBlock extends Block {
}
}
@@ -97,15 +100,16 @@ index 7135a6bc87f90fafa94d0783aaf7b42d66449010..afd06de092a75c6c4f7b8848055e314b
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && this.getSignalForState(state) > 0) {
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
index 504f38ce16f6a5d2b748a5c71c69f5be5886ceb5..db0b38db5675cb248e31e7a5988c35496561ad6f 100644
index bc79a7c2cb18237dad15432ae7e1238125108696..5ef16955c69f0e0fecc772067a0fb006e6413011 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
@@ -123,6 +123,24 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
}
}
@@ -125,16 +129,17 @@ index 504f38ce16f6a5d2b748a5c71c69f5be5886ceb5..db0b38db5675cb248e31e7a5988c3549
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
index bd6dc109fd9c37666f23ccd17c0eab8aff95e777..e25103c62a41e3fb0a8f7e84496cacc73ed71a74 100644
index aea12aad3270b966eed7779eaf77d26052f8a21f..6c39edf98f33df437880a77450557082ea9b0f6c 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);
@@ -80,6 +80,15 @@ public class BrewingStandBlock extends BaseEntityBlock {
level.addParticle(ParticleTypes.SMOKE, x, y, z, 0.0, 0.0, 0.0);
}
+ // Leaves start - behaviour 1.21.1-
@@ -144,16 +149,17 @@ index bd6dc109fd9c37666f23ccd17c0eab8aff95e777..e25103c62a41e3fb0a8f7e84496cacc7
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
index 27ca29f1d3e0e68229edef3b32634ce9b054824a..ea2c5d79fc41f58b263ec34b53df436e0043ef53 100644
index 86f4dcd959bb83247c6d2c5e947c79230aed3189..1b0223f1d533d1a8db5497ab9104052bc799f691 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();
@@ -131,6 +131,20 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
return pressed ? this.type.buttonClickOn() : this.type.buttonClickOff();
}
+ // Leaves start - behaviour 1.21.1-
@@ -168,15 +174,16 @@ index 27ca29f1d3e0e68229edef3b32634ce9b054824a..ea2c5d79fc41f58b263ec34b53df436e
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
index b9e11a361e91cf3d5c929330fc0ba59cfe903198..4985fcfef75abbe2be9cd5e6111de4d60237bafa 100644
index 8b706b34914326c039b761387f25e488f30fe6c8..b816594fcd83d26037734ec051f2c5d7f7dbde9f 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
@@ -111,6 +111,21 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
@@ -193,16 +200,17 @@ index b9e11a361e91cf3d5c929330fc0ba59cfe903198..4985fcfef75abbe2be9cd5e6111de4d6
+ }
+ }
+ // 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
protected void entityInside(
final BlockState state,
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
index fa2dce759419f62825000718361f47c6f208cdb2..64c0616c294bd7c7b62ae376d50369500b948390 100644
index d3f0680d59ec87990b54dc3dbce27706bfadf5f1..b5595d87339e4d313c5691a06c2b1b3d1b40b6de 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;
@@ -257,6 +257,15 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
return this.chestCanConnectTo(state) && state.getValue(TYPE) == ChestType.SINGLE ? state.getValue(FACING) : null;
}
+ // Leaves start - behaviour 1.21.1-
@@ -212,15 +220,16 @@ index fa2dce759419f62825000718361f47c6f208cdb2..64c0616c294bd7c7b62ae376d5036950
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
index cea0f015290137a5284f4a3021c954272b3db543..53d983505b4c92824083ecd123901874d04704c5 100644
index 0682acaae12650549eea3c291d8cde7bb17766bd..ac12ef0c99c82d771e5275ec7ced7f76c76f5938 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
@@ -168,6 +168,28 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
}
@@ -244,15 +253,16 @@ index cea0f015290137a5284f4a3021c954272b3db543..53d983505b4c92824083ecd123901874
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
index 3faa541c4a4623e915269d6241e1a3a3c6e374ff..18c660893a33ecf70c3d225525505852e4449182 100644
index 2b97fd6af1c4956eb173b8c66c2a3efc8772a798..90326fe95673edbf5ed8c1a5d9020735fdd4d53e 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 {
@@ -130,6 +130,15 @@ public class CrafterBlock extends BaseEntityBlock {
}
}
@@ -263,15 +273,16 @@ index 3faa541c4a4623e915269d6241e1a3a3c6e374ff..18c660893a33ecf70c3d225525505852
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
index dfb9a10622ba2a0c2759bb563fefd729f1109865..c735e7de1b88de531dd00a2cc2dd4a1394b808e6 100644
index 3dd5f8c20ad68e0bd6222c8ba1687df0b2ad3b0d..b2e1e78cd70e20dd1c17ef0199059fc2b4e513b5 100644
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
@@ -152,6 +152,17 @@ public class CreakingHeartBlock extends BaseEntityBlock {
builder.add(AXIS, STATE, NATURAL);
}
@@ -284,16 +295,17 @@ index dfb9a10622ba2a0c2759bb563fefd729f1109865..c735e7de1b88de531dd00a2cc2dd4a13
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
index dd20e3c57352859ab931692445c83669da94f629..e8c216831b66cd0f4e989797030119388a3378a5 100644
index 3ce41ce3f9d2bf7a79e4b9811e043a69e0dedb13..2856b4081cddb38bac5c1d7199649a7531ef077f 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);
@@ -172,6 +172,15 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
return new DecoratedPotBlockEntity(worldPosition, blockState);
}
+ // Leaves start - behaviour 1.21.1-
@@ -303,15 +315,16 @@ index dd20e3c57352859ab931692445c83669da94f629..e8c216831b66cd0f4e98979703011938
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
index b34e051b4a672d44872a74e810f978373e73af05..4525d718016fe125e3cdb1c1798fe9483213ba49 100644
index 3457a1fa8f5efc4bf173bf155165ab5e5ae9f303..1342607e3bf28ca085f51ade22efaf34f19da170 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 {
@@ -180,6 +180,17 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
}
@@ -324,15 +337,16 @@ index b34e051b4a672d44872a74e810f978373e73af05..4525d718016fe125e3cdb1c1798fe948
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
index 2ef2861041f3aaf85ea64458c43c5d83fdab9bfc..0828d663647f7c3267a4a9392a3b0b8e6e54928c 100644
index dca954bd076fa917512af91e0b93d449eb5cac6d..7f880ba7cdd08be392dd4fe5a06fffbf6962318b 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 {
@@ -159,6 +159,15 @@ public class DispenserBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
}
@@ -343,15 +357,16 @@ index 2ef2861041f3aaf85ea64458c43c5d83fdab9bfc..0828d663647f7c3267a4a9392a3b0b8e
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
index 3c349b4216d934068c26017820884593662f471e..4c5a12784e97e599891d40d5ce784b4f8c1e5b15 100644
index 88606b84ea3a33ffbb0cfa6e073eb8f59d7188d0..c3ccebd7f27fd4d313cbcd616d58180a70f5f574 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.
@@ -139,6 +139,15 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
}
}
@@ -362,15 +377,16 @@ index 3c349b4216d934068c26017820884593662f471e..4c5a12784e97e599891d40d5ce784b4f
+ 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) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
index a4b824dab307705559a76b954a3e47d30dd65889..bc036d8e9d241ea9178808fce39c4e5115d5f753 100644
index a9e46a66ffc868c3b4ef2bb6257f23a20f12b1a6..cee96a825f0e0e740ede8df0bf6dc5256b9fb8d3 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 {
@@ -82,6 +82,20 @@ public class JukeboxBlock extends BaseEntityBlock {
}
}
@@ -386,15 +402,16 @@ index a4b824dab307705559a76b954a3e47d30dd65889..bc036d8e9d241ea9178808fce39c4e51
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
index 52b9bd310c731c407fc4264559084debec81d3d9..0b991825d48ad64c1c68fd7c6bded7583572dded 100644
index 75660fb19c25444e35dbbe58cd20f9b3d3f7ad32..196051c80baa489f43065a11a61f22a8c61251e7 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 {
@@ -200,6 +200,37 @@ public class LecternBlock extends BaseEntityBlock {
changePowered(level, pos, state, false);
}
@@ -427,15 +444,16 @@ index 52b9bd310c731c407fc4264559084debec81d3d9..0b991825d48ad64c1c68fd7c6bded758
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
index 5f03e9fed3d4a8c3b72ca05be0b62ef45ac291f7..359fe5d611bcebe4cb98b9d8cea26b255adb167e 100644
index 341960ef67a689f660d0dcf61aaf5bf52bdc9074..6fc372e782f2a34a34a9ef1faed41ace6db5ec1b 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 {
@@ -127,6 +127,20 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
}
}
@@ -451,15 +469,16 @@ index 5f03e9fed3d4a8c3b72ca05be0b62ef45ac291f7..359fe5d611bcebe4cb98b9d8cea26b25
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
index dbfe086123c4b3cdc866111e1b6ec37d8d38d394..adad6e538b128729b72b7d44cabbd0cfba7417f9 100644
index 47ca45518df306cc4368983eefb89294e56b015a..31be8864aa28eff804b507efdab614b35e3fea6f 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
@@ -123,6 +123,19 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
}
}
@@ -474,15 +493,16 @@ index dbfe086123c4b3cdc866111e1b6ec37d8d38d394..adad6e538b128729b72b7d44cabbd0cf
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
index 3c12d8e23f20b666b0005e597ba2e803c02d5d78..17c371f4c24e8a81705bdd322b1de5de4b8be8b7 100644
index 6a3413ca875ce78f48cd8d3ce2cfe7798be1a19e..be572eff561ffdd961a9602eaa6136761c4d48a4 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 {
@@ -128,6 +128,18 @@ public class ObserverBlock extends DirectionalBlock {
}
}
@@ -496,15 +516,16 @@ index 3c12d8e23f20b666b0005e597ba2e803c02d5d78..17c371f4c24e8a81705bdd322b1de5de
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 48f9e234e4025633cbc41d334d88ada36c2e0d7b..5c154d15e5aa45988436722595c7fca74e166c9a 100644
index 30a7208a698a8bd3ba8a08ace6f23b206d90f6a3..7f5b77cd9cb78e693bbe1efd3d5fd7256d7700c5 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 {
@@ -382,6 +382,28 @@ public class RedStoneWireBlock extends Block {
}
}
@@ -528,15 +549,16 @@ index 48f9e234e4025633cbc41d334d88ada36c2e0d7b..5c154d15e5aa45988436722595c7fca7
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
index d1dbfc821f068f14bf975842f66251816ea5c985..fe13504a7d2d685e43183dd7b3219f1605570adb 100644
index 0d0b5443c5c56825e88fd64c02c993eca6044d45..e2e5552008547fa1782b0a5ed3129162e94647c9 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 {
@@ -54,6 +54,16 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
}
}
@@ -548,15 +570,16 @@ index d1dbfc821f068f14bf975842f66251816ea5c985..fe13504a7d2d685e43183dd7b3219f16
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
index 80e6ba8f026a6565696f18304507b2d0a347650c..593fab3d2a70bcd6832dd777afa4973f22abbaeb 100644
index 2bbce50d9dd0ca65f9e3bc90c8de098473039bc5..9a9fcb593c4b5f2bb0c57f9268dfdc9eb21d38ea 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
@@ -129,6 +129,19 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
}
}
@@ -571,16 +594,17 @@ index 80e6ba8f026a6565696f18304507b2d0a347650c..593fab3d2a70bcd6832dd777afa4973f
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
index 2815fb48530de3a2f9ef0f472a0fd0a2c32140b6..6b5e5bbbeb11bd8ce100ef3c215dfcf4b387e595 100644
index d7e5ec23c64b60c47ab6b54cbf282e88c3a4a045..037aa3592a963bbb142465d31040f60e95cb146e 100644
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
super.stepOn(level, pos, state, entity);
@@ -68,6 +68,17 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
super.stepOn(level, pos, onState, entity);
}
+ // Leaves start - behaviour 1.21.1-
@@ -592,15 +616,16 @@ index 2815fb48530de3a2f9ef0f472a0fd0a2c32140b6..6b5e5bbbeb11bd8ce100ef3c215dfcf4
+ 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) {
protected void tick(final BlockState state, final ServerLevel level, final BlockPos pos, final RandomSource random) {
if (state.getValue(SHRIEKING)) {
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 77840814806c7d07b58cd716cf7ec095e894498a..e820cd03e695649a8f83e23ae822524a8f78e23b 100644
index 722ce78461b2303f99493c309345697cfc98fb99..45dc3e8484842265b26d387d518831ff23da4b5e 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -150,6 +150,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@@ -150,6 +150,20 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
// Paper end - re-set loot table if it was cleared
}
@@ -616,15 +641,16 @@ index 77840814806c7d07b58cd716cf7ec095e894498a..e820cd03e695649a8f83e23ae822524a
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
index 9d005c3db8f0c784cdd7217e7b110daa703a9cf3..190d7cd818f768bd44fc1b4e62af2c9b3aacbe4d 100644
index 04e5995409a3532947dfab1c8ef05bd546a6f66d..6bf811477a27bbbeeeba6c9d768d33fc677ea5e7 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 {
@@ -107,6 +107,17 @@ public class TripWireBlock extends Block {
}
}
@@ -637,16 +663,17 @@ index 9d005c3db8f0c784cdd7217e7b110daa703a9cf3..190d7cd818f768bd44fc1b4e62af2c9b
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
index 42a5e9a7f5d604e4821a116ba13319df052faf97..e90e142cfb15335522a48ad82aa90018ed8ec349 100644
index fd808353181e05f2fc527a391ce7bb990f61b4c7..836eae0c3e0891a3e3309b684f15d65f891215cf 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);
@@ -248,6 +248,26 @@ public class TripWireHookBlock extends Block {
level.updateNeighborsAt(pos.relative(front), block, orientation);
}
+ // Leaves start - behaviour 1.21.1-
@@ -667,29 +694,30 @@ index 42a5e9a7f5d604e4821a116ba13319df052faf97..e90e142cfb15335522a48ad82aa90018
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java
index 6a9d23d25a79c73d5792011faf0e5a1c4c25bc64..84e0d3cd3c349f0d588a4b4c2d6844480a92b4ca 100644
index ac58bbed01edaf5dfe4839c89649ca865c339c8a..caead1012ff3b5b5f78c24a3baf20b7d00b84cf6 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> {
@@ -301,7 +301,7 @@ public class BlockEntityType<T extends BlockEntity> {
}
public boolean isValid(BlockState state) {
public boolean isValid(final 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
index 2b6ad989e1e1424d0283bae39e5dae33eba44923..0f47fb528422d591bd03434a089ea69c7f27bf8c 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);
@@ -70,6 +70,19 @@ public class MovingPistonBlock extends BaseEntityBlock {
return createTickerHelper(type, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
}
+ // Leaves start - behaviour 1.21.1-
@@ -703,15 +731,16 @@ index 58b78e6b9a43605940420d8cb0f1163ee3f0a5ff..eebf03ece11052f07702951b9335bc15
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
+
@Override
public void destroy(LevelAccessor level, BlockPos pos, BlockState state) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
public void destroy(final LevelAccessor level, final BlockPos pos, final BlockState state) {
BlockPos relative = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index b369e80a4fc371a3762e34e7d4d180b86d1d190f..0b412e360b090dc85d1726eb8f51c69b47061276 100644
index f8caa0b3c21766dbad73c524c1680346e4257188..b658d602953ade618d89c02745eb46be5d0175dd 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
@@ -78,6 +78,20 @@ public class PistonHeadBlock extends DirectionalBlock {
return super.playerWillDestroy(level, pos, state, player);
}
@@ -727,15 +756,16 @@ index b369e80a4fc371a3762e34e7d4d180b86d1d190f..0b412e360b090dc85d1726eb8f51c69b
+ }
+ }
+ // 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());
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
BlockPos basePos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4daf68cfd3 100644
index 0fbdf810c785c8a596d461e7651361fdedbb6217..ff1471f40b73582df68efbf2996a854c6aa37d65 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
@@ -174,6 +174,16 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
}
@@ -748,10 +778,11 @@ index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4d
+ }
+ // Leaves end - behaviour 1.21.1-
+
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
+
protected void affectNeighborsAfterRemoval(final BlockState state, final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
}
@@ -866,6 +875,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
@@ -889,6 +899,13 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
// CraftBukkit end
}
@@ -761,51 +792,52 @@ index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4d
+ }
+ // Leaves end - behaviour 1.21.1-
+
public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) {
+
public void affectNeighborsAfterRemoval(final ServerLevel level, final BlockPos pos, final boolean movedByPiston) {
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 5551d80a81c2878136f96b3e695c4888c7105a49..73dd8e67938fbfff745b189c06a93174976ba1bf 100644
index 316b8d45b0902b1bf01a77307e24fc9a47d1283b..9b3775b0cbca782964e03935331d1bfdd1af140d 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) {
@@ -424,22 +424,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
boolean blockChanged = !oldState.is(newBlock);
boolean movedByPiston = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0;
boolean sideEffects = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
- if (blockChanged && oldState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(oldState)) {
- if (!this.level.isClientSide() && sideEffects) {
- BlockEntity blockEntity = this.level.getBlockEntity(pos);
- if (blockEntity != null) {
- blockEntity.preRemoveSideEffects(pos, blockState);
- blockEntity.preRemoveSideEffects(pos, oldState);
+ // 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) {
+ if (blockChanged && oldState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(oldState)) {
+ if (!this.level.isClientSide() && sideEffects) {
+ BlockEntity blockEntity = this.level.getBlockEntity(pos);
+ if (blockEntity != null) {
+ blockEntity.preRemoveSideEffects(pos, blockState);
+ blockEntity.preRemoveSideEffects(pos, oldState);
+ }
}
- }
- this.removeBlockEntity(pos);
- }
+ this.removeBlockEntity(pos);
+ }
+ this.removeBlockEntity(pos);
+ }
- if ((flag || block instanceof BaseRailBlock)
- if ((blockChanged || newBlock instanceof BaseRailBlock)
- && this.level instanceof ServerLevel serverLevel
- && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ if ((flag || block instanceof BaseRailBlock)
- && ((flags & Block.UPDATE_NEIGHBORS) != 0 || movedByPiston)) {
- oldState.affectNeighborsAfterRemoval(serverLevel, pos, movedByPiston);
+ if ((blockChanged || newBlock instanceof BaseRailBlock)
+ && this.level instanceof ServerLevel serverLevel
+ && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
+ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ && ((flags & Block.UPDATE_NEIGHBORS) != 0 || movedByPiston)) {
+ oldState.affectNeighborsAfterRemoval(serverLevel, pos, movedByPiston);
+ }
+ } else {
+ blockState.onRemove(this.level, pos, state, flag1);
+ oldState.onRemove(this.level, pos, state, movedByPiston);
}
+ // Leaves end - behaviour 1.21.1-
if (!section.getBlockState(i, i1, i2).is(block)) {
if (!section.getBlockState(localX, localY, localZ).is(newBlock)) {
return null;
@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Wed, 3 Jun 2026 02:20:00 +0800
Subject: [PATCH] MiniTweaks mob fire and explosion rules
diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java
index 5005f2b923aa94dbc38fb75d5b6f58344888c895..0d4ba81c82b683c32addf6441de3843abf462c3c 100644
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -250,7 +250,8 @@ public class Creeper extends Monster {
if (!event.isCancelled()) {
// CraftBukkit end
this.dead = true;
- level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
+ Level.ExplosionInteraction explosionInteraction = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.noCreeperBlockBreaking ? Level.ExplosionInteraction.NONE : Level.ExplosionInteraction.MOB; // Lophine - MiniTweaks noCreeperBlockBreaking
+ level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), explosionInteraction); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(level, Entity.RemovalReason.KILLED);
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
diff --git a/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java b/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
index 711b97aa9e49b7edee34c91d77b1005be4fa96bd..1d9232c9061bde9c545e3ee25bc9c6b0417b9ece 100644
--- a/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
+++ b/net/minecraft/world/entity/projectile/hurtingprojectile/LargeFireball.java
@@ -37,7 +37,9 @@ public class LargeFireball extends Fireball {
// CraftBukkit start - fire ExplosionPrimeEvent
org.bukkit.event.entity.ExplosionPrimeEvent event = new org.bukkit.event.entity.ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
if (event.callEvent()) {
- this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
+ Level.ExplosionInteraction explosionInteraction = fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.noGhastBlockBreaking ? Level.ExplosionInteraction.NONE : Level.ExplosionInteraction.MOB; // Lophine - MiniTweaks noGhastBlockBreaking
+ boolean createFire = event.getFire() && !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.disableGhastFire; // Lophine - MiniTweaks disableGhastFire
+ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), createFire, explosionInteraction);
}
// CraftBukkit end - fire ExplosionPrimeEvent
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
diff --git a/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java b/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
index 1a72ee1559f75660796a9cbc1a9d9cdd6883dc90..480042d9401b6d7618fc2f36f16145606414d475 100644
--- a/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
+++ b/net/minecraft/world/entity/projectile/hurtingprojectile/SmallFireball.java
@@ -63,7 +63,7 @@ public class SmallFireball extends Fireball {
super.onHitBlock(hitResult);
if (this.level() instanceof ServerLevel serverLevel) {
Entity owner = this.getOwner();
- if (this.isIncendiary) { // CraftBukkit
+ if (this.isIncendiary && (!(owner instanceof Mob) || !fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.disableBlazeFire)) { // CraftBukkit // Lophine - MiniTweaks disableBlazeFire
BlockPos pos = hitResult.getBlockPos().relative(hitResult.getDirection());
if (this.level().isEmptyBlock(pos) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), pos, this).isCancelled()) { // CraftBukkit
this.level().setBlockAndUpdate(pos, BaseFireBlock.getState(this.level(), pos));
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Carpet Features Compatible
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 4bd923b42d1c98ce7178e05f9324f46d99ffc933..55bd9581c8c4bd3b1b7ba75cc80c94cf7548638a 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -340,7 +340,7 @@ public final class RegionizedServer {
final long tickStartNanos = System.nanoTime(); // Lophine - Carpet features
++this.tickCount;
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
MinecraftServer.getServer().tickRateManager().tick();
}
// Luminol end - Add a config to enable tick command
@@ -531,7 +531,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final long tickCount) {
- if ((!me.earthme.luminol.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
+ if ((!fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command // Lophine - redirect
world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + tickCount);
}
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index a37f392146ccc0319cf56ee0058ae8782b598fe3..2223f0b38e8f628af64d1c916fb2310c4704a407 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -576,7 +576,7 @@ public final class TickRegionScheduler {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
MinecraftServer.getServer().tickRateManager().endTickWork();
}
// Luminol end - Add a config to enable tick command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 74ef76058e5a410d12f88aa09450e7d90f63b5e6..1761167da363cd074a26499caadeaeb916461706 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -268,7 +268,7 @@ public class Commands {
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
// Luminol start - Add a config to enable tick command
- if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) { // Lophine - redirect
TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
}
// Luminol end - Add a config to enable tick command
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 8ed9aa981883458d11f8cddce56e04b021026cc2..fb200adb544a9cc5eb7d9d0051a6c70da017b858 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2188,7 +2188,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.lastSentFood = -1;
this.teleportSpectators(transition, oldLevel);
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot
}
// Leaves end - bot support
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index baa295f3dd8cf10bf7347ee4d1c249b1f82c9279..1d5376650d0f5eeb23fde8d7116b47cfae37576f 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -280,7 +280,7 @@ public abstract class PlayerList {
// org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
if (bot != null) {
this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -441,7 +441,7 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
if (bot != null) {
this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
@@ -969,7 +969,7 @@ public abstract class PlayerList {
).callEvent();
// Paper end
// Leaves start - bot support
- if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled()) {
this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(player, true)); // Leaves - render bot
}
// Leaves end - bot support
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index ac5b419169f8574f92ff7195bfa76c9978bc8a63..8066cdcaba8d2fcfa2e9ba3b040a2867dbbc6978 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -240,7 +240,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
// Leaves start - Wool hopper counter
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, entity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
if (woolColor != null) {
for (int i = 0; i < Short.MAX_VALUE; i++) {
@@ -258,7 +258,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (changed) {
entity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
// Leaves start - Wool hopper counter
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
entity.setCooldown(0);
return true;
}
@@ -668,7 +668,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static boolean addItem(final Container container, final ItemEntity entity) {
- if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && entity.isRemoved()) return false; // Leaves - Wool hopper counter
+ if (fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig.hopperCountersUnlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && entity.isRemoved()) return false; // Leaves - Wool hopper counter
boolean changed = false;
// CraftBukkit start
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
diff --git a/net/minecraft/world/level/dimension/end/EnderDragonFight.java b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
index 5ca008b3dca83c00f2ae86a608d726972a8d9f9d..125d5f59bdfdee5aa4bae2aa4756db363ee17f4b 100644
--- a/net/minecraft/world/level/dimension/end/EnderDragonFight.java
+++ b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
@@ -323,7 +323,7 @@ public class EnderDragonFight extends SavedData {
private int cachePortalOriginIteratorY = -1;
public BlockPattern.@Nullable BlockPatternMatch findExitPortal() {
- if (me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig.optimizedRespawn) {
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.optimizedDragonRespawn) { // Lophine - Carpet Features Compatible
int i, j;
for (i = cachePortalChunkIteratorX; i <= 8; ++i) {
for (j = cachePortalChunkIteratorZ; j <= 8; ++j) {
@@ -50,7 +50,7 @@ index a5f2e4454258886536251288c3694f58386c7420..28371ecf31d5fc280aaa03ed9a86f5b5
private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://papermc.io)";
private static final Gson GSON = new Gson();
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5effe76734b4 100644
index 4ada790812957657d580cb748077c4961987d0cb..ddf3ad20e7ce967d9e096345f99c55abf066c3b3 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
@@ -31,7 +31,7 @@ public record ServerBuildInfoImpl(
@@ -58,7 +58,7 @@ index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5eff
private static final String BRAND_PAPER_NAME = "Paper";
- private static final String BRAND_LUMINOL_NAME = "Luminol";
+ private static final String BRAND_LOPHINE_NAME = "Lophine";
+ private static final String BRAND_LOPHINE_NAME = "Lophine"; // Lophine - Rebrand to Lophine
private static final String BUILD_DEV = "DEV";
@@ -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,7 +41,7 @@ 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 9d5fe6fc727948955d89f9ed5e181185393a9611..1343972a3a230dcef7349f014a80362ffcb0fe94 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
@@ -85,7 +85,7 @@ public class CraftInventory implements Inventory {
@@ -49,7 +49,7 @@ index 9d5fe6fc727948955d89f9ed5e181185393a9611..1343972a3a230dcef7349f014a80362f
@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) {
@@ -5,7 +5,7 @@ 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..6c108bc7d93196803daeef4751d06cafa6eeec1a 100644
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 {
@@ -35,12 +35,13 @@ index 14ffbcb66006878eacf310547dad53718f8308eb..6c108bc7d93196803daeef4751d06caf
this.scheduleInternal(ret, initialDelayTicks);
@@ -133,7 +135,33 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
@@ -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()) {
@@ -70,11 +71,11 @@ index 14ffbcb66006878eacf310547dad53718f8308eb..6c108bc7d93196803daeef4751d06caf
private static final int STATE_IDLE = 0;
private static final int STATE_EXECUTING = 1;
@@ -145,13 +173,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
@@ -145,13 +174,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private final long repeatDelay; // in ticks
private Consumer<ScheduledTask> run;
private volatile int state;
+ private int taskId; // Lophine - add task id
+ private final int taskId; // Lophine - add task id
private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
@@ -87,7 +88,7 @@ index 14ffbcb66006878eacf310547dad53718f8308eb..6c108bc7d93196803daeef4751d06caf
}
private final int getStateVolatile() {
@@ -262,5 +292,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
@@ -262,5 +293,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
}
@@ -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 507204301b5e3cd545e66c510842c0a6391f0241..dfcfc83474443638e30f87d54472e5a38947dfad 100644
index ba0779211405b8b83f7c7e7b1c55b3e4846029a3..5f685b07878443bfe5f63147a0728df0708d79ad 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -485,6 +485,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 507204301b5e3cd545e66c510842c0a6391f0241..dfcfc83474443638e30f87d54472e5a3
}
public boolean getCommandBlockOverride(String command) {
@@ -1059,6 +1060,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");
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6f9f62263 100644
index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..d0b763f07aee56f69a67c87d7dd15a44b6f44db7 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -36,6 +36,15 @@ class PaperEventManager {
@@ -16,7 +16,7 @@ index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6
// SimplePluginManager
public void callEvent(@NotNull Event event) {
+ // Leaves start - process bot load/save
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable && fun.bm.lophine.config.modules.function.FakeplayerConfig.canResident) {
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.checkEnabled() && fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig.fakePlayerResident) {
+ if (event instanceof org.bukkit.event.world.WorldLoadEvent worldLoadEvent) {
+ org.leavesmc.leaves.bot.BotList.INSTANCE.loadResume(worldLoadEvent.getWorld().getUID().toString());
+ } else if (event instanceof org.bukkit.event.world.WorldUnloadEvent worldUnloadEvent) {
@@ -41,10 +41,10 @@ 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 21d594a39d09b2d17f05c40ce5323d57949d0b0b..46859fc70795097366f02dba48fdaab8b9c85013 100644
index 5339ff469a38d35e72ea7227503a84395462f84a..d75b4ecb24f2ea42afc82ac255775d8f35121fe5 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -374,6 +374,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");
@@ -53,10 +53,10 @@ index 21d594a39d09b2d17f05c40ce5323d57949d0b0b..46859fc70795097366f02dba48fdaab8
if (nmsEntity.level() != this.getHandle().getLevel()) {
throw new IllegalArgumentException(entity + " wasn't created with this world, you must create the entity with the world you want to add it to.");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a807517fd199b5 100644
index 5f685b07878443bfe5f63147a0728df0708d79ad..0eb89fc127738e02e8d4d49418b83baaffe00cbd 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -305,6 +305,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 dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a80751
// 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
@@ -486,6 +487,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 dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a80751
}
public boolean getCommandBlockOverride(String command) {
@@ -1379,7 +1381,7 @@ public final class CraftServer implements Server {
@@ -1377,7 +1379,7 @@ public final class CraftServer implements Server {
return false;
}
@@ -81,9 +81,9 @@ index dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a80751
return false;
}
@@ -3041,6 +3043,13 @@ public final class CraftServer implements Server {
this.console.addPluginAllowingSleep(plugin.getName(), value);
@@ -3113,6 +3115,13 @@ public final class CraftServer implements Server {
}
// Leaves end - Feature API
+ // Leaves start - Bot API
+ @Override
@@ -96,10 +96,10 @@ index dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a80751
/**
* 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 dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee118cc0692 100644
index 03ad9254c4b5556119fe73d533ceac7073b8fe74..fd2e24b6219219fa1fe7d2ba1d877ee4c24676ca 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -247,7 +247,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 dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee1
}
@Override
@@ -1121,9 +1121,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 dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee1
HumanEntity bukkitEntity = human.getBukkitEntity();
if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) {
@@ -1622,7 +1622,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 dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee1
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player.getX(), player.getY(), player.getZ(), seed, null));
}
}
@@ -1650,7 +1650,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,7 +138,7 @@ index dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee1
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player, seed, null));
}
} else if (emitter instanceof CraftEntity craftEntity) {
@@ -1791,7 +1791,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(
@@ -148,7 +148,7 @@ index dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee1
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 e6cd1c4a50b32b74f70a264e869b1ab4ac9b9eb0..6867064de52d810f1fd3869463ae27868ed0fb07 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
@@ -127,6 +127,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@@ -161,10 +161,10 @@ index e6cd1c4a50b32b74f70a264e869b1ab4ac9b9eb0..6867064de52d810f1fd3869463ae2786
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 0429ffda4aa4410f6f53bd163be8dee71b134637..9274f4ef639ed9b3028321566173d6612663082b 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
@@ -1014,7 +1014,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
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 100644
index d0b763f07aee56f69a67c87d7dd15a44b6f44db7..bd301425f4c3cdf2b2bd22c1775b7ca9be1d4248 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -57,7 +57,7 @@ class PaperEventManager {
@@ -21,10 +21,10 @@ index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9de
}
// Leaves end - skip bot
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 973f064fc5e089dc892d4b4077a807517fd199b5..06766a9058595aeee25e8fd3e3d01aeec2a55116 100644
index 0eb89fc127738e02e8d4d49418b83baaffe00cbd..53e49df883ec0fab984f2329d044d12ed6b1edff 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -306,6 +306,7 @@ public final class CraftServer implements Server {
@@ -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
@@ -32,7 +32,7 @@ index 973f064fc5e089dc892d4b4077a807517fd199b5..06766a9058595aeee25e8fd3e3d01aee
// 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
@@ -400,7 +401,7 @@ public final class CraftServer implements Server {
@@ -398,7 +399,7 @@ public final class CraftServer implements Server {
public CraftServer(DedicatedServer console, PlayerList playerList) {
this.console = console;
this.playerList = (DedicatedPlayerList) playerList;
@@ -41,7 +41,7 @@ index 973f064fc5e089dc892d4b4077a807517fd199b5..06766a9058595aeee25e8fd3e3d01aee
@Override
public CraftPlayer apply(ServerPlayer player) {
return player.getBukkitEntity();
@@ -3114,4 +3115,11 @@ public final class CraftServer implements Server {
@@ -3186,4 +3187,11 @@ public final class CraftServer implements Server {
}
}
// Folia end - region TPS API
@@ -54,7 +54,7 @@ index 973f064fc5e089dc892d4b4077a807517fd199b5..06766a9058595aeee25e8fd3e3d01aee
+ // 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 6867064de52d810f1fd3869463ae27868ed0fb07..69a0de762cfde089e8aaa6e6be79a8c8298d7778 100644
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 {
@@ -66,10 +66,10 @@ index 6867064de52d810f1fd3869463ae27868ed0fb07..69a0de762cfde089e8aaa6e6be79a8c8
// 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 6e745c7ddf417ec2fdcf102edd6a592047b5f73e..2f59107642d43719159872d5df37107d8a1a5b97 100644
index 47926ff2fba43bb83e2d9747420a526cce8ebe65..e72cd3c9919978a0ed91614d51d018bfb2cdb900 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2085,7 +2085,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
@@ -2086,7 +2086,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
@Override
public boolean canSee(Player player) {
@@ -79,10 +79,10 @@ index 6e745c7ddf417ec2fdcf102edd6a592047b5f73e..2f59107642d43719159872d5df37107d
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 6f608ad5d1151925ad0f38596dfe15290d20d753..9c1a48dd4a8957200d8c05cf7e142c621132bb74 100644
index fa3e2bf2b31ca5173d71082e93eb7eaa4faa2816..bd3c4eb10489f13562b31f4b809e80b19717bc25 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -344,7 +344,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
@@ -347,7 +347,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
}
@@ -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,98 @@
package fun.bm.lophine.carpet;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
import fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import fun.bm.lophine.protocol.CarpetLoggerProtocol;
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() {
CarpetLoggerProtocol.refreshConfiguredDefaults(!init);
registerProtocolRules();
init = true;
}
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", FakeplayerConfig.enable));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandPlayer", FakePlayerCompatConfig.commandPlayer));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerResident", FakePlayerCompatConfig.fakePlayerResident));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "openFakePlayerInventory", FakePlayerCompatConfig.openFakePlayerInventory));
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", WoolHopperCounterConfig.hopperCounters));
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", WoolHopperCounterConfig.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,122 @@
package fun.bm.lophine.carpet;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.mojang.logging.LogUtils;
import io.papermc.paper.threadedregions.RegionizedWorldData;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
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<RegionizedWorldData, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
public static boolean hasNoCollision(ServerLevel world, AABB bb) {
if (!TickThread.isTickThreadFor(world, bb)) return world.noCollision(bb);
int minX = Mth.floor(bb.minX);
int minY = Mth.floor(bb.minY);
int minZ = Mth.floor(bb.minZ);
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) {
RegionizedWorldData data = level.getCurrentWorldData();
if (data == null) return createMob(level, entityType);
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level.getCurrentWorldData(), key -> new HashMap<>());
Mob mob = cache.get(entityType);
if (mob != null && !mob.isRemoved()) {
if (!TickThread.isTickThreadFor(mob)) return createMob(level, entityType);
return mob;
}
return createMob(level, entityType);
}
public static @Nullable Mob createMob(ServerLevel level, EntityType<?> entityType) {
try {
if (entityType.create(level, EntitySpawnReason.NATURAL) instanceof Mob created) {
PRECOOKED_MOBS.get(level.getCurrentWorldData()).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.getCurrentWorldData());
if (cache != null) {
cache.remove(entityType);
}
}
}
@@ -0,0 +1,162 @@
package fun.bm.lophine.carpet;
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
import fun.bm.lophine.carpet.config.modules.WoolHopperCounterConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import me.earthme.luminol.config.ConfigManager;
import me.earthme.luminol.config.ConfigsInstance;
public class RedirectedConfigs {
public static void redirect() {
updateSuppressionCrashFix();
commandTick();
optimizedDragonRespawn();
woolHopperCounter();
fakeplayer();
creativeFlyNoClip();
redstoneChanges();
}
private static void updateSuppressionCrashFix() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
try {
boolean updateSuppressionCrashFixEnabled = config.getConfigOrigin("fixes.update-suppression-crash-fix.enabled");
if (updateSuppressionCrashFixEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.amsUpdateSuppressionCrashFix = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "amsUpdateSuppressionCrashFix"}, true);
GeneralCompatConfig.yeetUpdateSuppressionCrash = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "yeetUpdateSuppressionCrash"}, true);
}
config.removeConfig(new String[]{"fixes", "update-suppression-crash-fix", "enabled"});
} catch (Exception ignored) {
}
}
private static void commandTick() {
try {
boolean shouldEnabled = false;
// first check lophine
try {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
shouldEnabled = config.getConfigOrigin("experiment.command.tick_command_enabled");
config.removeConfig(new String[]{"experiment", "command", "tick_command_enabled"});
} catch (Exception ignored) {
}
// then check luminol
try {
ConfigsInstance config = ConfigManager.getConfigs("luminol");
shouldEnabled = shouldEnabled || (boolean) config.getConfigOrigin("experiment.command.enable_tick_command");
config.removeConfig(new String[]{"experiment", "command", "enable_tick_command"});
} catch (Exception ignored) {
}
if (shouldEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.commandTick = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "commandTick"}, true);
}
} catch (Exception ignored) {
}
}
private static void optimizedDragonRespawn() {
ConfigsInstance config = ConfigManager.getConfigs("luminol");
try {
boolean optimizedDragonRespawnEnabled = config.getConfigOrigin("optimizations.end_dragon.optimized_dragon_respawn");
if (optimizedDragonRespawnEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.optimizedDragonRespawn = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "optimizedDragonRespawn"}, true);
}
config.removeConfig(new String[]{"optimizations", "end_dragon", "optimized_dragon_respawn"});
} catch (Exception ignored) {
}
}
private static void woolHopperCounter() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean woolHopperCounterEnabled = config.getConfigOrigin("function.wool-hopper-counter.enabled");
if (woolHopperCounterEnabled) {
WoolHopperCounterConfig.hopperCounters = true;
carpetConfig.setConfig(new String[]{"carpet", "hopper_counter", "hopperCounters"}, true);
}
config.removeConfig(new String[]{"function", "wool-hopper-counter", "enabled"});
} catch (Exception ignored) {
}
try {
boolean woolHopperCounterUnlimitedSpeed = config.getConfigOrigin("function.wool-hopper-counter.unlimited-speed");
if (woolHopperCounterUnlimitedSpeed) {
WoolHopperCounterConfig.hopperCountersUnlimitedSpeed = true;
carpetConfig.setConfig(new String[]{"carpet", "hopper_counter", "hopperCountersUnlimitedSpeed"}, true);
}
config.removeConfig(new String[]{"function", "wool-hopper-counter", "unlimited-speed"});
} catch (Exception ignored) {
}
}
private static void fakeplayer() {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean bot = carpetConfig.getConfigOrigin("carpet.fakeplayer.commandBot");
if (bot) {
try {
ConfigsInstance lophineConfig = ConfigManager.getConfigs("lophine");
FakeplayerConfig.enable = true;
lophineConfig.setConfig(new String[]{"function", "fakeplayer", "enable"}, true);
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
}
carpetConfig.removeConfig(new String[]{"carpet", "fakeplayer", "commandBot"});
}
private static void creativeFlyNoClip() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
try {
boolean creativeFlyNoClipEnabled = config.getConfigOrigin("function.creative_fly_no_clip.enabled");
if (creativeFlyNoClipEnabled) {
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
GeneralCompatConfig.creativeNoClip = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "creativeNoClip"}, true);
}
config.removeConfig(new String[]{"function", "creative_fly_no_clip", "enabled"});
} catch (Exception ignored) {
}
}
private static void redstoneChanges() {
ConfigsInstance config = ConfigManager.getConfigs("lophine");
ConfigsInstance carpetConfig = ConfigManager.getConfigs("lophine_carpet");
try {
boolean dustTrapdoorReintroduced = config.getConfigOrigin("experiment.redstone.redstone-ignore-upwards-update");
if (dustTrapdoorReintroduced) {
GeneralCompatConfig.dustTrapdoorReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "dustTrapdoorReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "redstone-ignore-upwards-update"});
} catch (Exception ignored) {
}
try {
boolean shulkerBoxCCEReintroduced = config.getConfigOrigin("experiment.redstone.cce-update-suppression");
if (shulkerBoxCCEReintroduced) {
GeneralCompatConfig.shulkerBoxCCEReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "shulkerBoxCCEReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "cce-update-suppression"});
} catch (Exception ignored) {
}
try {
boolean instantBlockUpdaterReintroduced = config.getConfigOrigin("experiment.redstone.instant-block-updater");
if (instantBlockUpdaterReintroduced) {
GeneralCompatConfig.instantBlockUpdaterReintroduced = true;
carpetConfig.setConfig(new String[]{"carpet", "general", "instantBlockUpdaterReintroduced"}, true);
}
config.removeConfig(new String[]{"experiment", "redstone", "instant-block-updater"});
} catch (Exception ignored) {
}
}
}
@@ -0,0 +1,86 @@
package fun.bm.lophine.carpet.config.modules;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.command.bot.BotCommand;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
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 = "commandPlayer", comments = """
Enable /player command.(not remapped)
If you want to enable bot command, please see lophine global config.""")
public static boolean commandPlayer = false;
@ConfigInfo(name = "fakePlayerResident", comments = """
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;
@DoNotLoad
private BotCommand command = null;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (commandPlayer) {
command = new BotCommand("player");
command.register();
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (command != null) {
command.unregister();
command = null;
}
}
}
@@ -0,0 +1,278 @@
package fun.bm.lophine.carpet.config.modules;
import fun.bm.lophine.carpet.CarpetCompatSync;
import fun.bm.lophine.carpet.RedirectedConfigs;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "general",
directory = {"carpet"},
comments = """
Carpet/AMS/TIS/Org compatibility rules backed by existing Lophine features.
Only rules that already have a working server-side implementation are exposed here."""
)
public class GeneralCompatConfig implements IConfigModule {
@TransformedConfig(name = "language", directory = {"carpet", "general"}, transformComments = false)
@ConfigInfo(name = "language", comments = """
Carpet language value.
ATTENTION: This config will not update in Lophine global now!""")
public static String language = "en_us";
@ConfigInfo(name = "amsUpdateSuppressionCrashFix", comments = """
Update suppression crash protection.""")
public static boolean amsUpdateSuppressionCrashFix = false;
@ConfigInfo(name = "yeetUpdateSuppressionCrash", comments = """
Update suppression crash yeeting.""")
public static boolean yeetUpdateSuppressionCrash = false;
@ConfigInfo(name = "dustTrapdoorReintroduced", comments = """
Should the pre-1.20 mechanism be reintroduced:
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters,
and redstone comparators do not check for attachment when receiving status updates from below.""")
public static boolean dustTrapdoorReintroduced = false;
@ConfigInfo(name = "shulkerBoxCCEReintroduced", comments = """
Use ClassCastException for update suppression.""")
public static boolean shulkerBoxCCEReintroduced = false;
@ConfigInfo(name = "instantBlockUpdaterReintroduced", comments = """
Instant block updater.""")
public static boolean instantBlockUpdaterReintroduced = false;
@ConfigInfo(name = "commandTick", comments = """
Enable the tick command support.""")
public static boolean commandTick = false;
@ConfigInfo(name = "creativeNoClip", comments = """
Whether to enable creative fly no clip.
When enabled, players in creative mode will not collide with blocks while flying.
This allows them to pass through blocks without obstruction.""")
public static boolean creativeNoClip = false;
@ConfigInfo(name = "optimizedDragonRespawn", comments = """
Enable optimized dragon respawn.""")
public static boolean optimizedDragonRespawn = false;
@ConfigInfo(name = "antiSpamDisabled", comments = """
Disable the server-side chat and creative-drop spam throttles used by vanilla/Spigot.""")
public static boolean antiSpamDisabled = false;
@ConfigInfo(name = "blockPlacementIgnoreEntity", comments = """
Allow creative players to place blocks without entity collision checks.""")
public static boolean blockPlacementIgnoreEntity = false;
@ConfigInfo(name = "creativeOpenContainerForcibly", comments = """
Allow creative players to forcibly open blocked chests, ender chests and shulker boxes.""")
public static boolean creativeOpenContainerForcibly = false;
@ConfigInfo(name = "creativeOneHitKill", comments = """
Allow creative players to instantly kill attackable non-creative, non-spectator entities.
Sneaking expands the effect into a small area attack.""")
public static boolean creativeOneHitKill = false;
@ConfigInfo(name = "observerNoDetection", comments = """
Disable observer detection pulses entirely.""")
public static boolean observerNoDetection = false;
@ConfigInfo(name = "bambooModelNoOffset", comments = """
Remove the random horizontal model offset from bamboo and bamboo saplings.""")
public static boolean bambooModelNoOffset = false;
@ConfigInfo(name = "creativeNoItemCooldown", comments = """
Skip item cooldown application for creative players.""")
public static boolean creativeNoItemCooldown = false;
@ConfigInfo(name = "ctrlQCraftingFix", comments = """
Compatibility flag for the upstream result-slot Ctrl+Q crafting fix already present in the current menu code.""")
public static boolean ctrlQCraftingFix = false;
@ConfigInfo(name = "carpetAlwaysSetDefault", comments = """
Compatibility flag for Lophine's config loader, which already writes default values into the compat config during preload.""")
public static boolean carpetAlwaysSetDefault = false;
@ConfigInfo(name = "placementRotationFix", comments = """
Use the player's main body rotation for placement direction checks instead of interpolated head yaw.""")
public static boolean placementRotationFix = false;
@ConfigInfo(name = "tntDoNotUpdate", comments = """
Prevent TNT from checking redstone power when first placed.""")
public static boolean tntDoNotUpdate = false;
@ConfigInfo(name = "totallyNoBlockUpdate", comments = """
Suppress neighbor and shape updates globally for block changes.""")
public static boolean totallyNoBlockUpdate = false;
@ConfigInfo(name = "tiscmNetworkProtocol", comments = """
Enable the native Carpet TIS Addition network channel on `tiscm:network/v1`.""")
public static boolean tiscmNetworkProtocol = false;
@ConfigInfo(name = "hopperNoItemCost", comments = """
Restore the transferred stack into a hopper when a wool block is placed on top of it.""")
public static boolean hopperNoItemCost = false;
@ConfigInfo(name = "explosionNoBlockDamage", comments = """
Let explosions damage entities without breaking blocks.""")
public static boolean explosionNoBlockDamage = false;
@ConfigInfo(name = "noCreeperBlockBreaking", comments = """
Disables creeper explosion block breaking.""")
public static boolean noCreeperBlockBreaking = false;
@ConfigInfo(name = "noGhastBlockBreaking", comments = """
Disables ghast fireball explosion block breaking.""")
public static boolean noGhastBlockBreaking = false;
@ConfigInfo(name = "disableBlazeFire", comments = """
Disables fire made from blaze fireballs.""")
public static boolean disableBlazeFire = false;
@ConfigInfo(name = "disableGhastFire", comments = """
Disables fire made from ghast fireballs.""")
public static boolean disableGhastFire = false;
@ConfigInfo(name = "optimizedTNTHighPriority", comments = """
Compatibility flag for the already optimized server explosion path carried by the current runtime.""")
public static boolean optimizedTNTHighPriority = false;
@ConfigInfo(name = "tntPrimerMomentumRemoved", comments = """
Remove the random horizontal launch momentum from newly primed TNT.""")
public static boolean tntPrimerMomentumRemoved = false;
@ConfigInfo(name = "tntIgnoreRedstoneSignal", comments = """
Ignore redstone power when deciding whether TNT should auto-prime.""")
public static boolean tntIgnoreRedstoneSignal = false;
@ConfigInfo(name = "tntDupingFix", comments = """
Toggle the piston desync path used by vanilla TNT duplication setups.""")
public static boolean tntDupingFix = false;
@ConfigInfo(name = "interactionUpdates", comments = """
Control whether player interaction block changes emit normal block updates.
Set to false to suppress neighbor and shape updates during block use and breaking.""")
public static boolean interactionUpdates = true;
@ConfigInfo(name = "xpNoCooldown", comments = """
Allow players to absorb multiple experience orbs in the same tick without pickup delay.""")
public static boolean xpNoCooldown = false;
@ConfigInfo(name = "powerfulExpMending", comments = """
Let picked-up experience repair all damaged mending items in the player's inventory, not only equipped gear.""")
public static boolean powerfulExpMending = false;
@ConfigInfo(name = "clientSettingsLostOnRespawnFix", comments = """
Reapply the player's last known client settings after respawn.""")
public static boolean clientSettingsLostOnRespawnFix = false;
@ConfigInfo(name = "sensibleEnderman", comments = """
Restrict enderman block pickup to pumpkins and melons only.""")
public static boolean sensibleEnderman = false;
@ConfigInfo(name = "entityInstantDeathRemoval", comments = """
Remove the normal 20gt delay before dead living entities are discarded.""")
public static boolean entityInstantDeathRemoval = false;
@ConfigInfo(name = "farmlandTrampledDisabled", comments = """
Prevent farmland from turning into dirt when entities land on it.""")
public static boolean farmlandTrampledDisabled = false;
@ConfigInfo(name = "shulkerGolem", comments = """
Allow a carved pumpkin on top of a shulker box to summon a shulker.""")
public static boolean shulkerGolem = false;
@ConfigInfo(name = "preventEndSpikeRespawn", comments = """
Skip obsidian spike regeneration during dragon respawn.""")
public static boolean preventEndSpikeRespawn = false;
@ConfigInfo(name = "yeetOutOfOrderChatKick", comments = """
Ignore out-of-order secure chat chain checks instead of invalidating the chat session.""")
public static boolean yeetOutOfOrderChatKick = false;
@ConfigInfo(name = "betterCraftableBoneBlock", comments = """
Add the AMS alternate bone block recipe that yields 3 bone blocks from 9 bones.""")
public static boolean betterCraftableBoneBlock = false;
@ConfigInfo(name = "betterCraftableDispenser", comments = """
Add the AMS alternate dispenser recipes using a dropper.""")
public static boolean betterCraftableDispenser = false;
@ConfigInfo(name = "viewDistance", comments = """
Override the dedicated server's startup view distance with the Carpet-compatible value.""")
public static int viewDistance = 12;
@ConfigInfo(name = "tickCommandPermission", comments = """
Override the `/tick` command permission level.
Accepts values in the range 0..4, where 2 matches old Carpet behavior and 3 keeps vanilla.""")
public static int tickCommandPermission = 3;
@ConfigInfo(name = "tickFreezeCommandToggleable", comments = """
Make `/tick freeze` toggle back to running when executed while the server is already frozen.""")
public static boolean tickFreezeCommandToggleable = false;
@ConfigInfo(name = "syncServerMsptMetricsData", comments = """
Broadcast live MSPT samples through the native TISCM protocol channel.""")
public static boolean syncServerMsptMetricsData = false;
@ConfigInfo(name = "simpleInGameCalculator", comments = """
Evaluate chat messages prefixed with `=` as a simple calculator expression and reply privately.""")
public static boolean simpleInGameCalculator = false;
@ConfigInfo(name = "microTiming", comments = """
Compatibility flag for the built-in region profiler and timing instrumentation carried by Folia/Moonrise.""")
public static boolean microTiming = false;
@ConfigInfo(name = "fastRedstoneDust", comments = """
Route redstone dust updates through the Alternate Current fast-update backend.""")
public static boolean fastRedstoneDust = false;
@ConfigInfo(name = "lagFreeSpawning", comments = """
Use the lightweight collision and precooked-mob spawning path for natural spawning checks.""")
public static boolean lagFreeSpawning = false;
@ConfigInfo(name = "optimizedFastEntityMovement", comments = """
Compatibility flag for the always-on Moonrise/Paper fast entity movement collision pipeline.""")
public static boolean optimizedFastEntityMovement = false;
@ConfigInfo(name = "optimizedHardHitBoxEntityCollision", comments = """
Compatibility flag for the always-on Moonrise/Paper hard-hitbox entity collision optimizations.""")
public static boolean optimizedHardHitBoxEntityCollision = false;
@ConfigInfo(name = "tntFuseDuration", comments = """
Override the default primed TNT fuse duration in ticks.
Accepts values in the range 0..32767.""")
public static int tntFuseDuration = 80;
@ConfigInfo(name = "defaultLoggers", comments = """
Carpet-style default logger subscriptions for players.
Examples: ["tps", "mob_caps", "counter white"]""")
public static List<String> defaultLoggers = List.of();
public static boolean mergedUpdateSuppressionCrashEnabled() {
return amsUpdateSuppressionCrashFix || yeetUpdateSuppressionCrash;
}
public static int normalizedTntFuseDuration() {
return Math.clamp(tntFuseDuration, 0, Short.MAX_VALUE);
}
public static int normalizedTickCommandPermission() {
return Math.clamp(tickCommandPermission, 0, 4);
}
@Override
public void beforeFinalLoad() {
// Should remove in next Minecraft version update
RedirectedConfigs.redirect();
// after all config updated, send changes to client
CarpetCompatSync.apply();
}
}
@@ -0,0 +1,16 @@
package fun.bm.lophine.carpet.config.modules;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"carpet", "core"})
@ConfigInfo(name = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
public static boolean enabled = true;
}
@@ -0,0 +1,50 @@
package fun.bm.lophine.carpet.config.modules;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.command.counter.CounterCommand;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "hopper_counter",
directory = {"carpet"},
comments = """
Hopper counter functions."""
)
public class WoolHopperCounterConfig 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;
@DoNotLoad
private static CounterCommand counterCommand = null;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (hopperCounters) {
if (counterCommand == null) {
counterCommand = new CounterCommand();
}
counterCommand.register();
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (counterCommand != null) {
counterCommand.unregister();
}
}
}
@@ -3,28 +3,20 @@ package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "command")
public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "tick_command_enabled", comments =
@ConfigInfo(name = "trigger_command_enabled", comments =
"""
Allow to use tick command""")
public static boolean tick = false;
Allow to use trigger command""")
public static boolean trigger = false;
@ConfigInfo(name = "function_command_enabled", comments =
"""
Allow to use function command""")
public static boolean function = false;
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint bar"})
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
@ConfigInfo(name = "waypoint_command_enabled", comments =
"""
Allow to use waypoint command and locator bar""")
public static boolean waypoint = false;
@ConfigInfo(name = "scoreboard_command_enabled", comments =
"""
Allow to use scoreboard command""")
@@ -39,4 +31,8 @@ public class CommandConfig implements IConfigModule {
"""
Log all process of save-all command to console""")
public static boolean logAllProcess = false;
@ConfigInfo(name = "save_all_command_timeout", directory = {"save_all_command"}, comments = """
Maximum seconds to save before the chunk report it is timeout.""")
public static long saveAllTimeout = 30;
}
@@ -3,8 +3,6 @@ package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
/*
@@ -13,22 +11,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
*/
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"experiment", "redstone-ignore-upwards-update"})
@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;
@TransformedConfig(name = "enabled", directory = {"experiment", "cce-update-suppression"})
@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;
}
@@ -4,35 +4,31 @@ import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.CommandSuggestions;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "container_expansion")
public class ContainerExpansionConfig implements IConfigModule {
@TransformedConfig(name = "barrel_rows", directory = {"misc", "container_expansion"})
@HotReloadUnsupported
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "barrel_rows", comments =
"""
range: 1~6""")
public static int barrelRows = 3;
@TransformedConfig(name = "enderchest_rows", directory = {"misc", "container_expansion"})
@HotReloadUnsupported
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "enderchest_rows", comments =
"""
range: 1~6""")
public static int enderchestRows = 3;
@TransformedConfig(name = "shulker_stackable_count", directory = {"function", "container_expansion"})
@TransformedConfig(name = "shulker_stackable_count", directory = {"misc", "container_expansion"})
@CommandSuggestions(suggest = {"1", "2", "32", "64"})
@ConfigInfo(name = "shulker_stackable_count", directory = {"shulker_box"}, comments =
"""
range: 1~64""")
public static int shulkerCount = 1;
@TransformedConfig(name = "same_nbt_shulker_stackable", directory = {"function", "container_expansion"})
@TransformedConfig(name = "same_nbt_shulker_stackable", directory = {"misc", "container_expansion"})
@ConfigInfo(name = "same_nbt_shulker_stackable", directory = {"shulker_box"})
public static boolean nbtShulkerStackable = false;
}
@@ -1,9 +1,11 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
@@ -15,7 +17,7 @@ import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(name = "enable", comments = """
Enable fakeplayer functionality""")
Enable fakeplayer functionality (/bot command)""")
public static boolean enable = true;
@ConfigInfo(name = "unable-fakeplayer-names", comments = """
@@ -38,14 +40,6 @@ public class FakeplayerConfig implements IConfigModule {
Regeneration amount for fakeplayers""")
public static double regenAmount = 0.0;
@ConfigInfo(name = "resident-fakeplayer", comments = """
Allow fakeplayers to be resident""")
public static boolean canResident = false;
@ConfigInfo(name = "open-fakeplayer-inventory", comments = """
Allow opening fakeplayer inventory""")
public static boolean canOpenInventory = false;
@ConfigInfo(name = "use-action", comments = """
Allow fakeplayers to use actions""")
public static boolean canUseAction = true;
@@ -82,28 +76,34 @@ public class FakeplayerConfig implements IConfigModule {
Enable locator bar for fakeplayers""")
public static boolean enableLocatorBar = false;
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
@DoNotLoad
private BotCommand command = null;
private boolean registered = false;
public static int getSimulationDistance(ServerBot bot) {
return simulationDistance == -1 ? bot.getBukkitEntity().getSimulationDistance() : simulationDistance;
}
public static ServerBot.TickType tickType() {
return FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer
? ServerBot.TickType.NETWORK
: ServerBot.TickType.ENTITY_LIST;
}
public static boolean checkEnabled() {
return enable || FakePlayerCompatConfig.commandPlayer;
}
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enable) {
command = new BotCommand();
command = new BotCommand("bot");
command.register();
registered = true;
}
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
if (registered) {
if (command != null) {
command.unregister();
command = null;
}
@@ -3,14 +3,24 @@ package fun.bm.lophine.config.modules.function;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "language")
public class LanguageConfig implements IConfigModule {
@TransformedConfig(name = "lang", directory = {"optimizations", "language"})
@HotReloadUnsupported
@ConfigInfo(name = "lang", comments = """
Please use the key from https://minecraft.wiki/w/Language
Sample of format: en_us zh_cn zh_hk zh_tw""")
Sample of format: en_us zh_cn zh_hk zh_tw
ATTENTION: If you want to edit language for carpet ststem,
please edit it in carpet config file.""")
public static String lang = "en_us";
@ConfigInfo(name = "full_blocking_load", comments = """
Whether to allow blocking server loading when loading localized language.
If you want only use your localized language to shown in your terminal,
you need to enable it.
WARNING: This may slow down the startup speed!""")
public static boolean full_blocking_load = false;
}

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