Compare commits

..

116 Commits

Author SHA1 Message Date
Helvetica Volubi e5cc20ba9b Update Luminol 2026-02-23 21:23:49 +08:00
Helvetica Volubi 46e7abe59c Update Luminol 2026-02-18 00:25:23 +08:00
Helvetica Volubi 40df6b9dfb Switch to release cannel
Update Luminol
2026-02-13 21:14:41 +08:00
Bacteriawa 5559fa8bcc Update Luminol 2026-02-13 16:21:55 +08:00
Helvetica Volubi 6319ddf78f [ci skip]update qodana (#131)
* qodana update test

use community version

* fix: update bug-report.yml and qodana.yaml for improved configuration clarity

* chore: configure Git user details for CI environment

* [ci skip]fix: update linter image in qodana.yaml to use community version

* fix: update linter and action versions to use latest releases

* Revert "chore: configure Git user details for CI environment"

This reverts commit e53b12ac49.

* fix: update qodana.yaml to exclude all files instead of just JavaFiles

* Revert "qodana update test"

This reverts commit 4aac78cb72.

* [ci skip]fix: update .gitignore and qodana.yaml for project structure changes
2026-02-08 01:20:10 +08:00
Bacteriawa e74300a756 Fix Server crash when using CCE #109 2026-02-08 00:02:31 +08:00
Bacteriawa d9674b4e7c Update Luminol 2026-02-07 23:20:40 +08:00
Helvetica Volubi 6d02f00ac0 Update Luminol to fix #127
fixes #127
2026-01-30 19:47:50 +08:00
Helvetica Volubi 2960e7d24f perf: add cache for replay api 2026-01-28 22:45:50 +08:00
Helvetica Volubi d950c6d3e8 Update Luminol 2026-01-26 23:48:23 +08:00
Helvetica Volubi 357c351b95 fix up version fetcher 2026-01-22 00:59:08 +08:00
Helvetica Volubi a780b13fcc Update Luminol 2026-01-21 21:37:37 +08:00
Helvetica Volubi cf80fc6a86 Update Luminol 2026-01-18 03:31:10 +08:00
Helvetica Volubi 20acc9ccf5 feat: add save-all support 2026-01-16 02:41:01 +08:00
Helvetica Volubi e49ab25111 simply fix for replay api
fixed https://github.com/MC-XiaoHei/ISeeYou/issues/70
2026-01-14 01:57:42 +08:00
Helvetica Volubi eed4457419 add removed check before all checks start in addEffects 2026-01-13 21:06:48 +08:00
Helvetica Volubi 429a0345d9 refactor(bot): delay some logic of extra load in fakeplayer spawn 2026-01-13 20:47:55 +08:00
Helvetica Volubi 670d4e39c9 Update Luminol 2026-01-13 19:30:32 +08:00
Helvetica Volubi 5d4ddb9a6b fix #124 (refix of #121) 2026-01-09 19:10:28 +08:00
Helvetica Volubi 0ad90dc36e Update Luminol 2026-01-07 17:13:18 +08:00
Helvetica Volubi 284810dfb8 fixes #121 2026-01-04 17:51:09 +08:00
Helvetica Volubi 0f67f445b9 Update Luminol 2026-01-04 12:32:42 +08:00
Helvetica Volubi 018cc61204 Update Luminol 2026-01-03 13:59:49 +08:00
Helvetica Volubi b9c3d8deea fix ender dragon caused server crash 2026-01-03 01:40:35 +08:00
Helvetica Volubi 0d5b289d65 Update Luminol 2026-01-03 01:04:31 +08:00
Helvetica Volubi 5b20ad2e2c Update Luminol 2025-12-29 23:39:50 +08:00
Helvetica Volubi 9fcce731d0 Update Luminol 2025-12-29 01:28:30 +08:00
Helvetica Volubi 0783c97224 Update Protocols from Leaves 2025-12-28 00:29:37 +08:00
Helvetica Volubi 300e891906 Update Luminol 2025-12-27 23:42:13 +08:00
Helvetica Volubi a3e0a3ee1a Update Wool Counter & FakePlayer code from Leaves 2025-12-27 20:39:17 +08:00
Helvetica Volubi b3703e2069 fix a bug in way point 2025-12-27 20:36:30 +08:00
Helvetica Volubi d3c8da4edb Update Luminol 2025-12-27 17:16:52 +08:00
Helvetica Volubi bed0bfff06 fix: refix waypoint
related issue: https://github.com/LuminolMC/Lophine/issues/110
2025-12-26 03:38:04 +08:00
Helvetica Volubi 238231b28b Update Luminol 2025-12-26 03:28:41 +08:00
Helvetica Volubi db772aaf62 fix: fix waypoint module 2025-12-23 10:07:28 +08:00
Helvetica Volubi b1bee59e6c Update Luminol 2025-12-23 10:06:50 +08:00
Helvetica Volubi a9d24bd32c Update Luminol 2025-12-21 01:31:40 +08:00
dependabot[bot] f299d5188d [ciskip]build(deps): bump JetBrains/qodana-action from 2025.2 to 2025.3 (#108)
Bumps [JetBrains/qodana-action](https://github.com/jetbrains/qodana-action) from 2025.2 to 2025.3.
- [Release notes](https://github.com/jetbrains/qodana-action/releases)
- [Commits](https://github.com/jetbrains/qodana-action/compare/v2025.2...v2025.3)

---
updated-dependencies:
- dependency-name: JetBrains/qodana-action
  dependency-version: '2025.3'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-21 01:30:55 +08:00
Helvetica Volubi bbcc85fa93 1.21.11 Early Access
waypoint has force disabled because of some serious bug
2025-12-18 09:42:25 +08:00
Helvetica Volubi c26d8d1ee3 [ci skip]before we start to update to 1.21.11, we need push to maven repo 2025-12-18 03:43:04 +08:00
Helvetica Volubi 7bc12d2487 fix: 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.
2025-12-17 00:26:36 +08:00
dependabot[bot] 2c3aa4b68e [ci skip]build(deps): bump actions/upload-artifact from 5 to 6 (#106)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  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>
2025-12-15 15:44:44 +08:00
Bacteriawa 91312b7a15 Update Luminol 2025-12-14 00:18:07 +08:00
Helvetica Volubi 77c412bfe8 feat: update concurrent in waypoint 2025-12-11 02:05:57 +08:00
Helvetica Volubi c06d875df7 feat: add optimized concurrent table for waypoint management 2025-12-10 15:22:58 +08:00
Helvetica Volubi 5e96851513 fix a bug in entities counter 2025-12-10 02:52:55 +08:00
Helvetica Volubi 91b3ad527c fix waypoint manager
we use thread safe method to load it
2025-12-10 01:49:10 +08:00
dependabot[bot] 959a1c346c [ci skip]build(deps): bump actions/checkout from 3 to 6 (#102)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 6.
- [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/v3...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2025-12-08 15:51:58 +08:00
Helvetica Volubi b594382a6a [ci skip] fixup ci 2025-12-07 19:06:04 +08:00
Helvetica Volubi 37f1b4e5f1 fix: fix some async bugs 2025-12-07 18:42:46 +08:00
mrhua269 af2af944bf Fix issues of photographer with folia region threading 2025-12-06 23:25:37 +08:00
mrhua269 54688d8e34 Fix issues of fakeplayer with folia region threading 2025-12-06 22:35:51 +08:00
Helvetica Volubi 7b7f0b6d1f [ci skip] fix up branch in qodana 2025-12-06 21:58:02 +08:00
Helvetica Volubi 0ab3983145 Update Luminol
We need to check folia-supported,so we update it now
2025-12-06 16:52:56 +08:00
Helvetica Volubi 24a9d5cea8 fix https://github.com/MC-XiaoHei/ISeeYou/issues/68#issuecomment-3619619509 2025-12-06 15:45:34 +08:00
Helvetica Volubi 8ee77c3354 [ci skip] remove unused check
we have checked in protocol manager
2025-12-06 15:45:12 +08:00
qodana-cloud[bot] 98df254bad [ci skip]Add qodana CI checks (#100)
* Add qodana.yaml file

* Add github workflow file

---------

Co-authored-by: Qodana Application <qodana-support@jetbrains.com>
2025-12-04 14:19:47 +08:00
Helvetica Volubi 19f001ad1b [ci skip] remove unused data 2025-12-04 14:05:46 +08:00
Helvetica Volubi 106dfeaa38 fix: fix global entity count max limit problem 2025-12-04 13:37:48 +08:00
Helvetica Volubi 403ae2b2d0 feat: chunkCount 2025-12-04 12:13:14 +08:00
Helvetica Volubi 96c99519d5 fix: fix an async bug
if latest task is not done, skip this tick so that we can not block thread and run the task have not done, after it done, the new data will be processed in the next tick
2025-12-03 20:33:13 +08:00
Helvetica Volubi 5c4031b836 [ci skip] fixup template & comment 2025-12-03 20:20:59 +08:00
Helvetica Volubi 376857ff97 feat: global entities counter
We provided a new way to use entities counter to spawn mobs, maybe have some bugs, so we set this to experiment config

 - Update file update
 - Update Luminol
2025-12-03 16:31:34 +08:00
Helvetica Volubi fa1ab90579 fix a ConcurrentModificationException caused by ServuxStructuresProtocol
Update Luminol
2025-11-30 15:53:28 +08:00
Creeam fc9c6937b6 Add LeavesConfig dummy class (#99)
For some plugin detections
2025-11-30 07:28:01 +00:00
Helvetica Volubi 12d8ba9050 Update Luminol 2025-11-29 06:03:01 +08:00
Helvetica Volubi 38a1ce0443 fix: fix crash caused by uncheck data access 2025-11-26 22:32:20 +08:00
dependabot[bot] a5a415e495 build(deps): bump actions/checkout from 5 to 6 (#93)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [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/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2025-11-24 08:21:49 +00:00
Helvetica Volubi b7bf1b5916 Update Luminol 2025-11-24 00:16:50 +08:00
Helvetica Volubi 4a8888c578 try fixes bugs caused by Bukkit.getScheduler().runTaskLater
we use (FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed to instead of Bukkit.getScheduler().runTaskLater, and we also provided a brand-new way to cancel task by task id
2025-11-22 01:57:16 +08:00
Helvetica Volubi 2c59a32afe [ci skip] Update context 2025-11-20 15:36:46 +08:00
Helvetica Volubi cc5382977d Update Luminol 2025-11-20 15:32:41 +08:00
xiaoxijun c07dde1c0b feat: CCE Update Suppression support and other dependences (#84)
add cce update suppression & prevent crashes caused by update suppres & dustTrapdoorReintroduced & instantBlockUpdater & old Block remove behaviour & do not reset placed block on exception & do not prevent block entity and entity crash at LevelChunk (#84)

* add cce update suppression & prevent crashes caused by update suppression

* no need for this transformed flag

* Add Redstone ignore upwards update

* fix up license

* move config

* instant Block Updater

* feat: Update Suppression!

* Leaves: Do not reset placed block on exception & Do not prevent block entity and entity crash at LevelChunk

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com>
2025-11-19 00:04:34 +08:00
Helvetica Volubi 871a003a2e Update Luminol to fix open-gui bug 2025-11-17 17:54:27 +08:00
Helvetica Volubi d6a981a6e9 [ci skip] skip release and push in unexpect branch
See https://github.com/LuminolMC/Luminol/commit/ec746a66f0813f60eb59de11b8207f773fc4728c
2025-11-17 17:26:24 +08:00
Helvetica Volubi bc166a9fb6 [ci skip] refactor code 2025-11-16 21:22:06 +08:00
Helvetica Volubi feebf388f8 Add Replay Api (#86)
* feat: base replay api support

* fix an async bug
2025-11-16 21:05:01 +08:00
Helvetica Volubi dbcf764e76 fix ServuxStructuresProtocol (#89)
* Add LeaveHooks to fix bug caused by servux structures protocol

* add missing file

* add comment

* add license
2025-11-16 20:51:19 +08:00
Helvetica Volubi 735fe8855a try to fix a bug in fake player spawn 2025-11-16 18:53:16 +08:00
Helvetica Volubi 1b45a090f6 Update Luminol 2025-11-16 14:09:42 +08:00
Helvetica Volubi bb1335d390 [ci skip] Update Luminol
do not release yet, release at next commit
2025-11-15 15:38:52 +08:00
Helvetica Volubi 00743c841f Update Luminol 2025-11-14 22:27:06 +08:00
xiaoxijun bdb9c9dec4 Add Alternative block placement Protocol (#81)
* Add Alternative block placement Protocol

* fix: fix config error caused by config system

- TODO: fix config system read enum bug in luminol

* remove Leaves logger & use mojang logger

* update code from leaves

---------

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

* Add AppleSkin protocols

* Add BBOR Protocol

* Add Jade Protocol

* Add Xaero Map Protocol

* Add Support REI protocol

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

* move config file directory

* add license & refactor code

* update leaves fix

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

* Update Luminol

* fix up jade protocol

* fix up rei

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com>
2025-10-20 00:06:40 +08:00
Helvetica Volubi 4cc49c6d99 fix: fix bot save command 2025-10-20 00:02:21 +08:00
Helvetica Volubi 93c0258c7e fix: use local lastTickCount to save data 2025-10-19 23:40:17 +08:00
Helvetica Volubi 43a5ea0385 Update Luminol 2025-10-18 02:34:13 +08:00
Helvetica Volubi 678882a435 Update Luminol & fix a bug in shutdown server 2025-10-14 19:14:12 +08:00
Helvetica Volubi 8e5884147f fix: fix async bugs
fixes #70
2025-10-12 11:54:30 +08:00
Helvetica Volubi b999cf9f5f [ci skip] update ci 2025-10-11 23:34:49 +08:00
Helvetica Volubi 847bcd54e0 Update Luminol 2025-10-06 14:20:14 +08:00
Helvetica Volubi 15a55403ff Modify merge ItemEntity logic
Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius, when the merge radius is large and stacks containing many items get stuck in an unexpected position, individual items may never reach their destination. This configuration option is added to fix this behavior.
2025-10-04 01:15:49 +08:00
Helvetica Volubi 482809df6e [ci skip]fix: fix default translations support 2025-10-03 18:24:30 +08:00
Helvetica Volubi 5db8ec4bd9 fix: pre fix a bug in I18n (will cause bug in 1.21.9) 2025-10-03 17:03:37 +08:00
Helvetica Volubi d60cd46c15 Update Luminol 2025-10-02 16:51:47 +08:00
281 changed files with 17082 additions and 1843 deletions
+17 -3
View File
@@ -1,7 +1,7 @@
name: Bug反馈 Bug report
description:
报告Bug,插件不兼容情况,以及其他相关问题。
Report issues with plugin incompatbility or other behavior related issues.
Report issues with plugin incompatibility or other behavior related issues.
labels:
- bug
- pending
@@ -25,7 +25,7 @@ body:
LophineMC服务端发行版本 LophineMC server release version (contains the git commit's hash)<br>
通过执行`/version`命令将获取到的内容复制到这里。 Run `/version` on your server and paste the full, unmodified output here.
placeholder: >
e.g. git-Lophine-"0635a89" (MC: 1.20.4)
e.g. git-Lophine-"fa1ab90" (MC: 1.21.8)
validations:
required: true
- type: textarea
@@ -41,7 +41,7 @@ body:
attributes:
label: 观测到的实际行为 Observed/Actual behavior
description: 你实际看到的。 What you actually saw.
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
validations:
required: true
- type: textarea
@@ -65,6 +65,20 @@ body:
To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
validations:
required: true
- type: textarea
id: config-file-list
attributes:
label: 配置文件列表(如果可以)。 Config File List (if possible).
description:
服务器上的配置文件列表。
All config files on your server.
例如以下文件(或者文件夹):
Example files (or folders)
- \spigot.yml
- \bukkit.yml
- \config\\\*
- \lophine_config\\\*
- \luminol_config\\\*
- type: textarea
id: other
attributes:
+1 -1
View File
@@ -28,7 +28,7 @@ body:
validations:
required: true
- type: textarea
id: othre
id: other
attributes:
label: 其他 Other
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
+28 -16
View File
@@ -10,13 +10,13 @@ on:
workflow_dispatch:
inputs:
force-release:
description: "Force release if you enter 1, default release if not released else skip release"
description: "Force disable release if you enter 2, force release if you enter 1, default release if not released else skip release"
required: false
default: "0"
default: ""
force-push:
description: "Push to repo if you enter 1, default push if not released else skip push repo"
description: "Force disable push to repo if you enter 2, force push to repo if you enter 1, default push if not released else skip push repo"
required: false
default: "0"
default: ""
comments:
description: "Add comments to release"
required: false
@@ -30,7 +30,7 @@ jobs:
environment: default
steps:
- name: Checkout Git Repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Set Up JDK
uses: actions/setup-java@v5
@@ -39,7 +39,7 @@ jobs:
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v5
- name: Grant execute permission for gradlew
run: chmod +x gradlew
@@ -50,16 +50,16 @@ jobs:
- name: Apply All Patches
run: ./gradlew --refresh-dependencies applyAllPatches
- name: CreateMojmapPaperclipJar
- name: Build Paperclip Jar
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
- name: Upload Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: ${{ env.project_id_b }} CI Artifacts
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
- name: SetENV
- name: Set Environment
if: github.event_name != 'pull_request'
run: sh scripts/SetENV.sh
@@ -84,8 +84,19 @@ jobs:
fi
echo "release_exists=${release_exists}" >> $GITHUB_ENV
- name: Publish to repo
if: (( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' ) || ( env.release_exists == 'true' && inputs.force-push == '1' )) && false # do not push to any repo
- name: Check If Branch In Expectations
if: github.event_name != 'pull_request'
run: |
if [[ "$GITHUB_REF_NAME" == ver/* ]] || [[ "$GITHUB_REF_NAME" == exp/* ]] || [[ "$GITHUB_REF_NAME" == dev/* ]]; then
echo "Branch is in expected prefixes"
echo "unexpect=false" >> $GITHUB_ENV
else
echo "Branch is NOT in expected prefixes"
echo "unexpect=true" >> $GITHUB_ENV
fi
- name: Publish To Repo
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1'
continue-on-error: true
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
env:
@@ -93,13 +104,14 @@ jobs:
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
- name: Create Release - Pre Process
if: ( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' ) || ( env.release_exists == 'true' && inputs.force-release == '1' )
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
run: |
if [ ${{ inputs.comments }} == "" ]; then
echo "No comments provided"
echo "flag_comment=true" >> $GITHUB_ENV
if [ "${{ inputs.comments }}" == "" ]; then
echo "No comments provided"
echo "flag_comment=false" >> $GITHUB_ENV
else
echo "flag_comment=false" >> $GITHUB_ENV
echo "Comments provided: ${{ inputs.comments }}"
echo "flag_comment=true" >> $GITHUB_ENV
fi
- name: Create Release - No Comment
+29
View File
@@ -0,0 +1,29 @@
name: Qodana
on:
workflow_dispatch:
pull_request:
push:
branches: # Specify your branches here
- ver/* # Stable branch
- exp/* # Experimental branch
- dev/* # Development Branch
jobs:
qodana:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@latest
with:
pr-mode: false
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1658551725 }}
QODANA_ENDPOINT: 'https://qodana.cloud'
+3 -5
View File
@@ -6,12 +6,10 @@ build
/run
/lightingluminol-server/build.gradle.kts
/lightingluminol-api/build.gradle.kts
/luminol-server/build.gradle.kts
/luminol-server/src/minecraft
/lophine-server/build.gradle.kts
/lophine-api/build.gradle.kts
/lophine-server/src/minecraft
/paper-server
/luminol-api/build.gradle.kts
/paper-api
/paper-api-generator
+2 -2
View File
@@ -62,7 +62,7 @@ repositories {
}
dependencies {
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
}
```
@@ -78,7 +78,7 @@ dependencies {
<dependencies>
<dependency>
<groupId>me.earthme.luminol</groupId>
<groupId>fun.bm.lophine</groupId>
<artifactId>luminol-api</artifactId>
<version>$VERSION</version>
</dependency>
+2 -2
View File
@@ -62,7 +62,7 @@ repositories {
}
dependencies {
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
}
```
@@ -78,7 +78,7 @@ dependencies {
<dependencies>
<dependency>
<groupId>me.earthme.luminol</groupId>
<groupId>fun.bm.lophine</groupId>
<artifactId>luminol-api</artifactId>
<version>$VERSION</version>
<scope>provided</scope>
+6 -3
View File
@@ -1,10 +1,13 @@
group=fun.bm.lophine
version=1.21.8-R0.1-SNAPSHOT
mcVersion=1.21.8
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
luminolRef=9c79e227fcbb2bdfa624e97f522ca36aa4901100
luminolRef=78a3b89f5850f71ddb5b1d1adeccda47f5762a1b
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.0.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+1 -1
View File
@@ -1,6 +1,6 @@
--- a/luminol-api/build.gradle.kts
+++ b/luminol-api/build.gradle.kts
@@ -103,20 +_,24 @@
@@ -104,20 +_,24 @@
srcDir(generatedDir)
srcDir(file("../paper-api/src/main/java"))
srcDir(file("../folia-api/src/main/java"))
@@ -1,14 +1,17 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 30 Aug 2025 16:51:26 +0800
Subject: [PATCH] Add fakeplayer api
Subject: [PATCH] Leaves: Add fakeplayer api
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113c1296d26 100644
index b9d34c0b80a5d0c26f43e4959c3a8256a854585a..850f65d764030b09d469e33a69409204503d9ca1 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -3052,4 +3052,15 @@ public final class Bukkit {
@@ -3039,4 +3039,15 @@ public final class Bukkit {
public static void restart() {
server.restart();
}
@@ -25,10 +28,10 @@ index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113
+ // Leaves end - Bot API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index a0540d7de5c2536aed5231f9e67b73345817921d..c7ae463fb166750bbd0638a2ccf81753b293a381 100644
index 1dc5d8c96786950fc98cada5bad981c0c716b154..cb8c4e09511f99558eb5af26c08c5cb1f936780d 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2753,4 +2753,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -2791,4 +2791,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
double @Nullable [] getRegionTPS(@NotNull World world, int chunkX, int chunkZ);
// Folia end - region TPS API
@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 16 Nov 2025 15:50:28 +0800
Subject: [PATCH] Leaves: Replay Mod API
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 850f65d764030b09d469e33a69409204503d9ca1..78b947352aa32ae0c59101459f420bf8e3497707 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 {
return server.getBotManager();
}
// Leaves end - Bot API
+
+ // Leaves start - Photographer API
+ public static @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager() {
+ return server.getPhotographerManager();
+ }
+ // Leaves end - Photographer API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index cb8c4e09511f99558eb5af26c08c5cb1f936780d..b770b6f990d46f5325554f5d73c6a2a6ed361158 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
*/
@NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager();
// Leaves end - Bot API
+
+ // Leaves start - Photographer API
+ @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager();
+ // Leaves end - Photographer API
}
@@ -39,9 +39,9 @@ public interface Bot extends Player {
/**
* Gets the fakeplayer name without prefix and suffix
*
* @return fakeplayer real name
* @return fakeplayer raw name
*/
@NotNull String getRealName();
@NotNull String getRawName();
/**
* Gets the creator's UUID of the fakeplayer
@@ -91,4 +91,13 @@ public interface Bot extends Player {
* @return success
*/
boolean remove(boolean save);
/**
* Remove the fakeplayer
*
* @param save should save
* @param resume should resume at next server start
* @return success
*/
boolean remove(boolean save, boolean resume);
}
@@ -27,8 +27,8 @@ import java.util.function.Consumer;
public interface BotCreator {
static BotCreator of(String realName, Location location) {
return Bukkit.getBotManager().botCreator(realName, location);
static BotCreator of(String rawName, Location location) {
return Bukkit.getBotManager().botCreator(rawName, location);
}
BotCreator name(String name);
@@ -61,5 +61,5 @@ public interface BotManager {
*/
<T extends BotAction<T>> T newAction(@NotNull Class<T> type);
BotCreator botCreator(@NotNull String realName, @NotNull Location location);
BotCreator botCreator(@NotNull String rawName, @NotNull Location location);
}
@@ -0,0 +1,43 @@
/*
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
*
* Leaves is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Leaves is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
*/
package org.leavesmc.leaves.entity.photographer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
public interface Photographer extends Player {
@NotNull String getId();
void setRecordFile(@NotNull File file);
void stopRecording();
void stopRecording(boolean async);
void stopRecording(boolean async, boolean save);
void pauseRecording();
void resumeRecording();
void setFollowPlayer(@Nullable Player player);
}
@@ -0,0 +1,44 @@
/*
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
*
* Leaves is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Leaves is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
*/
package org.leavesmc.leaves.entity.photographer;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.replay.BukkitRecorderOption;
import java.util.Collection;
import java.util.UUID;
public interface PhotographerManager {
@Nullable Photographer getPhotographer(@NotNull UUID uuid);
@Nullable Photographer getPhotographer(@NotNull String id);
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location);
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption);
void removePhotographer(@NotNull String id);
void removePhotographer(@NotNull UUID uuid);
void removeAllPhotographers();
Collection<Photographer> getPhotographers();
}
@@ -0,0 +1,35 @@
/*
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
*
* Leaves is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Leaves is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
*/
package org.leavesmc.leaves.replay;
public class BukkitRecorderOption {
// public int recordDistance = -1;
public String serverName = "Lophine"; // Lophine - rebrand to Lophine to avoid confusion
public BukkitRecordWeather forceWeather = BukkitRecordWeather.NULL;
public int forceDayTime = -1;
public boolean ignoreChat = false;
// public boolean ignoreItem = false;
public enum BukkitRecordWeather {
CLEAR,
RAIN,
THUNDER,
NULL
}
}
+7 -7
View File
@@ -1,6 +1,6 @@
--- a/luminol-server/build.gradle.kts
+++ b/luminol-server/build.gradle.kts
@@ -52,7 +_,23 @@
@@ -48,7 +_,23 @@
}
}
@@ -25,7 +25,7 @@
spigot {
@@ -142,12 +_,16 @@
@@ -139,12 +_,16 @@
resources { srcDir("../paper-server/src/main/resources") }
java { srcDir("../folia-server/src/main/java") }
resources { srcDir("../folia-server/src/main/resources") }
@@ -42,16 +42,16 @@
}
}
val log4jPlugins = sourceSets.create("log4jPlugins") {
@@ -174,7 +_,7 @@
@@ -172,7 +_,7 @@
}
dependencies {
- implementation(project(":luminol-api")) // Luminol
+ implementation(project(":lophine-api")) // Lophine
// Luminol start - Dependenices insert
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
implementation("com.github.luben:zstd-jni:1.5.4-1")
@@ -276,14 +_,14 @@
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 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
@@ -70,7 +70,7 @@
"Build-Number" to (build ?: ""),
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
@@ -447,7 +_,7 @@
@@ -432,7 +_,7 @@
}
fill {
@@ -5,27 +5,27 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 6f294437d8791487d559e52a23a859c0572c0034..4d7e7d7a9c16d416d0ba4c77be061718c9793cb1 100644
index 0bebc2cc87fb9c1c526e4de4f3bc157552307a72..cb1657939b86c039fcfe6403d3f202c2c5879e88 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -22,6 +22,7 @@ public class ConfigManager {
@@ -23,6 +23,7 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of(new File("luminol_config"), "luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", ConfigsInstance.of(new File("lophine_config"), "lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
preLoad();
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
index df5d926fb4401dd93d658fe14ae4d9d58cff68f9..b6d84fea596cfa78032151ab2f206b6b3d5dd197 100644
index e4022494b050b68d54bac3cde87bdfc9e908859c..a4188ef831825764c0756b826651e2e7a9f99c5b 100644
--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
@@ -8,7 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "server_mod_name")
public class ServerModNameConfig implements IConfigModule {
@ConfigInfo(name = "name")
@ConfigInfo(name = "name", comments = "Decides the server mod name shown in your F3 debug screen.")
- public static String serverModName = "Luminol";
+ public static String serverModName = "Lophine";
@ConfigInfo(name = "vanilla_spoof")
@ConfigInfo(name = "vanilla_spoof", comments = "Ignore any plugin's modification and server mod name set in this config block, only force sending brand name of vanilla")
public static boolean fakeVanilla = false;
@@ -5,26 +5,36 @@ 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 66ae993896ba38a7fa5302d4ff88a52e4a0bb72c..c6d53d720437f43a713469049de3d90d1082cd2e 100644
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
@@ -11,6 +11,7 @@ public class CommandConfig implements IConfigModule {
@TransformedConfig(name = "enable", directory = {"experiment", "force_the_data_command_to_be_enabled"})
@@ -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")
@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;
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
index 35e6014f04093050a9a62b895b43e5c5d8c6a28e..11abfb884f972fd73ca4c13a6e309de1bcd23fd5 100644
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
@@ -8,6 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "force_disable_packet_limiter_of_paper")
+ @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 = {"misc", "force_disable_packet_limiter_of_paper"})
@TransformedConfig(name = "force_disable", directory = {"optimizations", "force_disable_packet_limiter_of_paper"})
@ConfigInfo(name = "force_disable")
public static boolean forceDisable = false;
@@ -8,180 +8,69 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/d93e9766d3797d130
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981c4e34aed 100644
index 112dc08eb62c4c50fb4859f51a366cedf027ca00..b5f661fd20b382725ad117c56ce2c94ded32b1b7 100644
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
@@ -17,12 +17,173 @@
@@ -17,6 +17,7 @@
package org.leavesmc.leaves.util;
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
+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;
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 {
// Only the used part is retained
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 ((size = util.getMaxServerStackCount(stack)) != -1) {
+ return size;
+ }
+ }
+ return stack.getMaxStackSize();
+ }
+
+ public static int getNetworkMaxCount(ItemStack stack) {
+ int size;
+ for (ItemUtil util : overstackUtils) {
+ if ((size = util.getMaxClientStackCount(stack)) != -1) {
+ return size;
+ }
+ }
+ return stack.getMaxStackSize();
+ }
+
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
+ for (ItemUtil util : overstackUtils) {
+ if (util.tryStackItems(self, other)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean hasOverstackingItem() {
+ return overstackUtils.stream().anyMatch(ItemUtil::isEnabled);
+ }
+
+ 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());
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) {
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());
return Objects.equals(stack1.getComponents(), stack2.getComponents());
- }*/ // Luminol
+ }
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
+ }
+
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
+ }
+
+ @Override
+ public boolean isEnabled() {
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 ContainerExpansionConfig.shulkerCount > 1;
+ }
+
+ @Override
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
+ ItemStack selfStack = self.getItem();
+ if (!isEnabled() ||
}
@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;
+ }
+
+ ItemStack otherStack = other.getItem();
+ if (selfStack.getItem() == otherStack.getItem()
+ && shulkerBoxCheck(selfStack, otherStack)
) {
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
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
+
+ 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 (isEnabled() && stack.getItem() instanceof BlockItem bi &&
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
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
+ return ContainerExpansionConfig.shulkerCount;
+ }
+ return -1;
+ }
+ }
}
}
return -1;
}
@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 18 Feb 2026 00:15:08 +0800
Subject: [PATCH] Leaves: Fakeplayer
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
--- 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
return;
}
+ // Leaves start - fakeplayer
+ if (waypoint instanceof org.leavesmc.leaves.bot.ServerBot bot && !bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.ENABLE_LOCATOR_BAR)) {
+ return;
+ }
+ // Leaves end - fakeplayer
+
this.waypoints.add(waypoint);
for (ServerPlayer toCreateFor : this.trackingPlayers) {
@@ -91,6 +97,12 @@ public class FoliaServerWaypointManager implements WaypointManager<@NotNull Wayp
public void addPlayer(ServerPlayer player) {
this.trackingPlayers.add(player);
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
+
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
this.createConnection(player, waypointTransmitter);
}
@@ -1,60 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 16:30:54 +0800
Subject: [PATCH] Add config to allow infinite trade
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
index 79242037e868a140513f032e74e8594c0c6ff41c..050e89c3e95c7c3ef7ad98f8ef03ab206241a7e2 100644
--- a/net/minecraft/world/entity/npc/Villager.java
+++ b/net/minecraft/world/entity/npc/Villager.java
@@ -490,8 +490,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
private void resendOffersToTradingPlayer() {
- MerchantOffers offers = this.getOffers();
+ // Lophine start - infinite trade
+ MerchantOffers offers = this.getOffers().copy();
Player tradingPlayer = this.getTradingPlayer();
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
+ for (MerchantOffer merchantOffer : offers) {
+ merchantOffer.maxUses = 524288;
+ }
+ }
+ // Lophine end - infinite trade
if (tradingPlayer != null && !offers.isEmpty()) {
tradingPlayer.sendMerchantOffers(
tradingPlayer.containerMenu.containerId,
diff --git a/net/minecraft/world/item/trading/Merchant.java b/net/minecraft/world/item/trading/Merchant.java
index 6e2fa442ddcd4ef3c4fe789b9ebac9dd409c9de7..0c7318a0ed214204f5493576c8a7b02fbe51c00b 100644
--- a/net/minecraft/world/item/trading/Merchant.java
+++ b/net/minecraft/world/item/trading/Merchant.java
@@ -42,7 +42,14 @@ public interface Merchant {
new SimpleMenuProvider((containerId, inventory, player1) -> new MerchantMenu(containerId, inventory, this), displayName)
);
if (optionalInt.isPresent()) {
- MerchantOffers offers = this.getOffers();
+ // Lophine start - infinite trade
+ MerchantOffers offers = this.getOffers().copy();
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
+ for (MerchantOffer merchantOffer : offers) {
+ merchantOffer.maxUses = 5242884;
+ }
+ }
+ // Lophine end - infinite trade
if (!offers.isEmpty()) {
player.sendMerchantOffers(optionalInt.getAsInt(), offers, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock());
}
diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java
index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..770f37d7158c7b4cec62783025f623a68c1f2457 100644
--- a/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/net/minecraft/world/item/trading/MerchantOffer.java
@@ -196,7 +196,7 @@ public class MerchantOffer {
}
public boolean isOutOfStock() {
- return this.uses >= this.maxUses;
+ return (this.uses >= this.maxUses && !fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade); // Lophine - infinite trade
}
public void setToOutOfStock() {
@@ -1,55 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 3 Aug 2025 14:26:37 +0800
Subject: [PATCH] Disable some check for operators
Subject: [PATCH] Add config to disable some check for operators
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index f06b9d8ad9512d35f3f460eb77c869690321c67f..e17f9629369f8653b484b4cc71de4874b5faa4d6 100644
index bd344bbebc867f89061694edc0feeab9d679c90c..6d0bb9868e2c2ef516de7630442808c04ba47b39 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -367,7 +367,7 @@ public class ServerGamePacketListenerImpl
@@ -392,7 +392,7 @@ public class ServerGamePacketListenerImpl
this.tickCount++;
this.knownMovePacketCount = this.receivedMovePacketCount;
if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) {
- if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player)) {
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
// LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
// LOGGER.warn("{} was kicked for floating too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingPlayer, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause
return;
@@ -386,7 +386,7 @@ public class ServerGamePacketListenerImpl
return true;
@@ -411,7 +411,7 @@ public class ServerGamePacketListenerImpl
this.vehicleLastGoodY = this.lastVehicle.getY();
this.vehicleLastGoodZ = this.lastVehicle.getZ();
if (this.clientVehicleIsFloating && this.lastVehicle.getControllingPassenger() == this.player) {
- if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle)) {
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingVehicle, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause
return;
@@ -644,7 +644,7 @@ public class ServerGamePacketListenerImpl
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 && this.player.hasPermissions(2))) { // Spigot // Lophine - disable move check for operator
+ 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.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(d7));
}
@@ -1540,7 +1540,7 @@ public class ServerGamePacketListenerImpl
@@ -1564,7 +1564,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);
- if (!event.isAllowed()) {
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
if (event.getLogWarning()) {
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5);
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), d3, d4, d5);
}
@@ -1618,7 +1618,7 @@ public class ServerGamePacketListenerImpl
@@ -1643,7 +1643,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);
- if (!event.isAllowed()) {
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
movedWrongly = true;
if (event.getLogWarning())
// Paper end
@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 26 Aug 2025 02:55:23 +0800
Subject: [PATCH] Add config to allow generation of end void rings
diff --git a/net/minecraft/world/level/levelgen/DensityFunctions.java b/net/minecraft/world/level/levelgen/DensityFunctions.java
index 04527a5c65ad630f794fed9071d485aedd02257a..57e4c6c60f7d012a9de411b07d000f3504c27e6b 100644
--- a/net/minecraft/world/level/levelgen/DensityFunctions.java
+++ b/net/minecraft/world/level/levelgen/DensityFunctions.java
@@ -528,7 +528,7 @@ public final class DensityFunctions {
int i1 = z / 2;
int i2 = x % 2;
int i3 = z % 2;
- float f = 100.0F - Mth.sqrt((long)x * (long)x + (long)z * (long)z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
+ float f = fun.bm.lophine.config.modules.fixes.EndVoidRingsConfig.enabled ? 100.0F - Mth.sqrt(x * x + z * z) * 8.0F : 100.0F - Mth.sqrt((long)x * (long)x + (long)z * (long)z) * 8.0F; // Paper - cast ints to long to avoid integer overflow // Lophine - customize end void rings generation
f = Mth.clamp(f, -100.0F, 80.0F);
NoiseCache cache = noiseCache.get().computeIfAbsent(noise, noiseKey -> new NoiseCache()); // Paper - Perf: Optimize end generation
@@ -5,12 +5,12 @@ Subject: [PATCH] Add config to enable cross region damage trace
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 11e6197dec541b28733715f0d7eaa4c7b834d632..de1263404395c28209234a556347284fa557f81c 100644
index 08e0dde0aa5ff94b72127abcd7da2a63d5701db8..e311502c156076842c5dcd91c70a94e414312100 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1345,6 +1345,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -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, cause);
killCredit.awardKillScore(this, damageSource);
this.createWitherRose(killCredit);
+ // Luminol Start - Cross Region Damage trace
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
@@ -21,8 +21,8 @@ index 11e6197dec541b28733715f0d7eaa4c7b834d632..de1263404395c28209234a556347284f
+ // Luminol End - Cross Region Damage trace
}
this.level().broadcastEntityEvent(this, (byte)3);
@@ -1368,6 +1375,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.level().broadcastEntityEvent(this, EntityEvent.DEATH);
@@ -1468,6 +1475,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Leaves end - exp fix
@@ -48,10 +48,10 @@ index 11e6197dec541b28733715f0d7eaa4c7b834d632..de1263404395c28209234a556347284f
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc01846eaf7 100644
index c67c29278ea63ab8b936d53bf654089f2dba2eef..88d532d11c29bd8cfe5b6b02847d960b07cf0a38 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1948,6 +1948,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -1975,6 +1975,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
final LivingEntity killer = this.getKillCredit();
if (killer != null) {
killer.awardKillScore(this, damageSource);
@@ -65,7 +65,7 @@ index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc0
}
}); // Paper end
this.postDeathDropItems(deathEvent); // Paper
@@ -1958,6 +1965,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -1985,6 +1992,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
return deathEvent; // Paper
}
@@ -84,7 +84,7 @@ index 0c6d48363cd65cd22b4cc0ab97be977e133b64be..e94687b3aa960f9c630f459fedc17bc0
protected void dropEquipment(ServerLevel level) {
}
protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
@@ -2556,6 +2575,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -2612,6 +2631,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
}
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable raytracing tracker
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd16792507f 100644
index bca2c5410aa543d2bb421e53893e9163508b3568..fdccb06c918d387e46c29ede7337159db8c5d9ca 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1278,7 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -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;
// Paper start - Configurable entity tracking range by Y
@@ -18,19 +18,19 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 90c36bb87a761119edb376f3bd425d48d29bf36f..a720d8db40ca56c997a4eeae14ebbc6fe764892c 100644
index 040c0f8d26554ba583ecf370e2df3690d8f48dd6..22e68cabb4554c3e21e6f4ef316186f60ec77511 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
import org.jetbrains.annotations.Contract;
@@ -152,7 +152,7 @@ import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
-public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
-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
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
@@ -6474,4 +6474,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
static boolean isLevelAtLeast(ValueInput input, int level) {
@@ -6442,4 +6442,46 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -78,10 +78,10 @@ index 90c36bb87a761119edb376f3bd425d48d29bf36f..a720d8db40ca56c997a4eeae14ebbc6f
+
}
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b706e3273 100644
index 0590d5723854a03a59fe9471710802f4e64e50b8..4f8ff2c024d6f2e67c5fa38fe2e660ba39e35499 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1119,6 +1119,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1254,6 +1254,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
public final int passengerTickTimerId;
public final int passengerInactiveTickTimerId;
// Folia end - profiler
@@ -92,10 +92,10 @@ index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b
public EntityType(
EntityType.EntityFactory<T> factory,
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a6268fdaa46 100644
index 67c0f4027a1e8b364694b5ed8b71965f2fe9b359..0f6e1428cc71c370af45db3e2a4f47c66e5d8628 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -229,6 +229,25 @@ public abstract class Player extends LivingEntity {
@@ -189,6 +189,25 @@ public abstract class Player extends Avatar implements ContainerUser {
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
}
// CraftBukkit end
@@ -121,7 +121,7 @@ index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a62
public Player(Level level, GameProfile gameProfile) {
super(EntityType.PLAYER, level);
@@ -287,6 +306,26 @@ public abstract class Player extends LivingEntity {
@@ -245,6 +264,26 @@ public abstract class Player extends Avatar implements ContainerUser {
@Override
public void tick() {
@@ -148,8 +148,8 @@ index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a62
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
@@ -1426,6 +1465,7 @@ public abstract class Player extends LivingEntity {
if (this.containerMenu != null && this.hasContainerOpen()) {
@@ -1353,6 +1392,7 @@ public abstract class Player extends Avatar implements ContainerUser {
if (this.hasContainerOpen()) {
this.doCloseContainer();
}
+ if (this.cullTask != null) this.cullTask.signalStop(); // Luminol - Ray tracing entity tracker
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable function command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index af895859057ca303177ec3c8a07cf7534e62cca6..e0e9fcf3224f55f2ef31c8afca3154a5992f761b 100644
index 9c0c3835776bda3bab08f0abaffc89a72bba0bfc..b95d144dd479d339cc4b0f92cc4c3bade9af4927 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -206,7 +206,9 @@ public class Commands {
@@ -215,7 +215,9 @@ public class Commands {
FillCommand.register(this.dispatcher, context);
FillBiomeCommand.register(this.dispatcher, context);
ForceLoadCommand.register(this.dispatcher);
@@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 2 Jul 2025 23:36:25 +0800
Subject: [PATCH] Add config to enable datapack command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index e05f75b6bbd48d6fb7379926d68d5f8ed6014be9..af895859057ca303177ec3c8a07cf7534e62cca6 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -192,7 +192,9 @@ public class Commands {
if(me.earthme.luminol.config.modules.experiment.CommandConfig.data) {
DataCommands.register(this.dispatcher); // Folia - region threading - TODO
}
- //DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.datapack) {
+ DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ }
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
DefaultGameModeCommands.register(this.dispatcher);
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 75027e73859c955a54034640f905cb5d91a6a2f4..b4b3ff86f7c4afb94fc4da5133746391a078a7fb 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2353,6 +2353,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
}
+ // Lophine start - region thread skip reload // TODO - add reload support
+ public void saveDatapacks(Collection<String> selectedIds) {
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
+ );
+ this.worldData.setDataConfiguration(worldDataConfiguration);
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
+
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
// Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
index b540a3c3a02f7242578a63477e34b9063e86f1d2..9f0adf157872e1c68cd7752a24eacdc636e8d17a 100644
--- a/net/minecraft/server/commands/ReloadCommand.java
+++ b/net/minecraft/server/commands/ReloadCommand.java
@@ -16,6 +16,12 @@ public class ReloadCommand {
private static final Logger LOGGER = LogUtils.getLogger();
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
+ // Lophine start - region thread skip reload // TODO - add reload support
+ if (true) {
+ source.getServer().saveDatapacks(selectedIds);
+ return;
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
@@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 16 Jan 2026 02:34:43 +0800
Subject: [PATCH] Add config to enable save-all command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 17108636a5728efe98a064001e00e3ca098b1f51..7748e9ac04fbd3f5259d92fc908d90889cba86c8 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -350,6 +350,8 @@ public final class RegionizedServer {
// tick player ping sample
this.tickPlayerSample();
+ fun.bm.lophine.utils.SaveAllUtil.checkTimeout(); // Lophine - save-all fix
+
// tick worlds
for (final ServerLevel world : this.worlds) {
this.globalTick(world, tickCount);
diff --git a/io/papermc/paper/threadedregions/TickRegions.java b/io/papermc/paper/threadedregions/TickRegions.java
index 02c004bc7f9a0203523ce4b27cd766d6bdc478c0..3d86e21198f2888422330b6f7c27712f40a6aabc 100644
--- a/io/papermc/paper/threadedregions/TickRegions.java
+++ b/io/papermc/paper/threadedregions/TickRegions.java
@@ -190,6 +190,8 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
public final ThreadedRegionizer.ThreadedRegion<TickRegionData, TickRegionSectionData> region;
public final ServerLevel world;
+ public long lastSavedTime = 0; // Lophine - save-all fix
+
// generic regionised data
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 6cb0d4daf0f275b95d5ca09275e40ab32258eb39..48628174299f8f18170198df1834d6174bd1fafa 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -294,7 +294,11 @@ public class Commands {
PardonCommand.register(this.dispatcher);
PardonIpCommand.register(this.dispatcher);
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
- //SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Lophine start - Add a config to enable save all command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.saveAll) {
+ SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Lophine end - Add a config to enable save all command
SaveOffCommand.register(this.dispatcher);
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4be383909addfebc0ca3b007d4ef2ec30ed445f7..fa60388376e9dafc5e1b71b6e78550bb6cd4009b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1656,6 +1656,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) {
+ // Lophine start - save-all fix
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
+ }
+ // Lophine end - save-all fix
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
// Folia end - region threading
org.spigotmc.WatchdogThread.tick(); // Spigot
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
index e37b71402179c73146ff67babc228ccfb996f8f4..cfdb60bd89d83282f2202a5585bac22a6002e138 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 {
- 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) {
@@ -29,6 +31,12 @@ public class SaveAllCommand {
} else {
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
return 1;
- }
+ }*/
+ return 1;
}
+
+ public static SimpleCommandExceptionType getErrorFailed() {
+ return ERROR_FAILED;
+ }
+ // Lophine end - save all
}
@@ -5,11 +5,11 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index e0e9fcf3224f55f2ef31c8afca3154a5992f761b..6633af3cff77bcd4bcc591c032d647b7a850dced 100644
index 097e5b6a14fd148c93ca3894295a4a6b1e9aa870..bd8d98aa813b575e83138e79726bd3143268913c 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -231,7 +231,11 @@ public class Commands {
//RotateCommand.register(this.dispatcher); // Folia - region threading - TODO later
@@ -241,7 +241,11 @@ public class Commands {
RotateCommand.register(this.dispatcher);
SayCommand.register(this.dispatcher);
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
- //ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
@@ -1,14 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Thu, 1 May 2025 22:43:08 +0800
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add config to enable tick command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839621d73d7 100644
index 7748e9ac04fbd3f5259d92fc908d90889cba86c8..80b5d151e0dd6fa44794187875b4b80519839d81 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -299,6 +299,11 @@ public final class RegionizedServer {
@@ -332,6 +332,11 @@ public final class RegionizedServer {
this.randomWalk();
*/
++this.tickCount;
@@ -20,7 +20,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -322,6 +327,13 @@ public final class RegionizedServer {
@@ -357,6 +362,13 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
@@ -34,20 +34,20 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
// tick connections
this.tickConnections();
@@ -455,7 +467,7 @@ public final class RegionizedServer {
@@ -492,7 +504,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final int tickCount) {
private void tickTime(final ServerLevel world, final long tickCount) {
- if (world.tickTime) {
+ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
if (world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
world.setDayTime(world.levelData.getDayTime() + (long)tickCount);
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 c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722880f3b4e 100644
index 0f4e8ee9438135e24e0f61a1390c59573b9e9c3f..65699d2ad66c686a8b7d1b951787ddd766800a94 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -31,8 +31,8 @@ public final class TickRegionScheduler {
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
@@ -55,17 +55,17 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Luminol - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Luminol - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
@@ -394,8 +394,23 @@ public final class TickRegionScheduler {
static {
@@ -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 int tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Luminol start - Add a config to enable tick command
+ final int tickCount;
+ final long tickCount;
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
@@ -74,17 +74,17 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
+ } else {
+ TICK_RATE = MinecraftServer.tickRateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Luminol end - Add tick command support
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
@@ -435,6 +450,11 @@ public final class TickRegionScheduler {
@@ -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);
@@ -97,10 +97,10 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
this.scheduler.regionFailed(this, false, thr);
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc 100644
index bd8d98aa813b575e83138e79726bd3143268913c..65f200381f486146ce8d893378f0591a82f6076b 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -251,7 +251,11 @@ public class Commands {
@@ -262,7 +262,11 @@ public class Commands {
TeleportCommand.register(this.dispatcher);
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
@@ -114,23 +114,23 @@ index 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index b4b3ff86f7c4afb94fc4da5133746391a078a7fb..b156b5c635f931a3d4abc0584591f90476d011a6 100644
index 76098a4f44f8d82bebf832fa5e240adf25fbe80a..644c49730fc08a7c680f8114136db00ee8f81378 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private String serverId;
@@ -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;
public PotionBrewing potionBrewing;
private FuelValues fuelValues;
private LevelData.RespawnData effectiveRespawnData = LevelData.RespawnData.DEFAULT;
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c60d14fd87 100644
index 4257c47d33e3773fac766817138cc21c55d9ab76..95f6b1cbd5e33151c326689bc72292ff38a48803 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -105,7 +105,7 @@ public class ServerTickRateManager extends TickRateManager {
@@ -106,7 +106,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
@@ -139,7 +139,7 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c6
return true;
} else {
this.finishTickSprint();
@@ -113,6 +113,12 @@ public class ServerTickRateManager extends TickRateManager {
@@ -114,6 +114,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
@@ -153,7 +153,7 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c6
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index 126685fb266692082b432ed297a499149e921dfb..9d8f6025c420e651611da17e77a362c738228b72 100644
index 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;
@@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 2 Jul 2025 23:36:25 +0800
Subject: [PATCH] Fix datapack command save function
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d7d22806c010636d8c1471f0fd1d64ef54e92c97..8d96d2130cf3383427047fee97fa49155164e337 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);
}
+ // Lophine start - region thread skip reload // TODO - add reload support
+ public void saveDatapacks(Collection<String> selectedIds) {
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
+ );
+ this.worldData.setDataConfiguration(worldDataConfiguration);
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
+
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
// Paper end - Add ServerResourcesReloadedEvent
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
index bb36fa4559cdfe82079af1c39516239119ff06f4..8c530eef0e416d8b96f190ada358d77d34dbc8ac 100644
--- a/net/minecraft/server/commands/DataPackCommand.java
+++ b/net/minecraft/server/commands/DataPackCommand.java
@@ -98,7 +98,7 @@ public class DataPackCommand {
dispatcher.register(
Commands.literal("datapack")
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
- /*.then( // Luminol - Add back read-only datapack command
+ .then(
Commands.literal("enable")
.then(
Commands.argument("name", StringArgumentType.string())
@@ -160,11 +160,11 @@ public class DataPackCommand {
.suggests(SELECTED_PACKS)
.executes(commandContext -> disablePack(commandContext.getSource(), getPack(commandContext, "name", false)))
)
- )*/ // Luminol - Add back read-only datapack command
+ )
.then(
Commands.literal("list")
.executes(commandContext -> listPacks(commandContext.getSource()))
- // .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource()))) // Luminol - Add back read-only datapack command
+ .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource())))
.then(Commands.literal("enabled").executes(commandContext -> listEnabledPacks(commandContext.getSource())))
)
.then(
@@ -252,7 +252,7 @@ public class DataPackCommand {
}
private static int listPacks(CommandSourceStack source) {
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
+ return listEnabledPacks(source) + listAvailablePacks(source);
}
private static int listAvailablePacks(CommandSourceStack source) {
@@ -280,7 +280,7 @@ public class DataPackCommand {
private static int listEnabledPacks(CommandSourceStack source) {
PackRepository packRepository = source.getServer().getPackRepository();
- // packRepository.reload(); // Luminol - Add back read-only datapack command
+ packRepository.reload();
Collection<? extends Pack> selectedPacks = packRepository.getSelectedPacks();
if (selectedPacks.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.datapack.list.enabled.none"), false);
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
index fcca0babb4e7929cc168fc8b9ad47619e6feb1a5..bac5f4e023f8b73eebea0f31fd253e04c8809918 100644
--- a/net/minecraft/server/commands/ReloadCommand.java
+++ b/net/minecraft/server/commands/ReloadCommand.java
@@ -16,11 +16,17 @@ public class ReloadCommand {
private static final Logger LOGGER = LogUtils.getLogger();
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
+ // Lophine start - region thread skip reload // TODO - add reload support
+ source.getServer().saveDatapacks(selectedIds);
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
+ if (false) {
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure"));
return null;
});
+ }
+ // Lophine end - region thread skip reload // TODO - add reload support
}
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
@@ -1,92 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 18:19:00 +0800
Subject: [PATCH] Add config to enable waypoint command & bar
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc..9eee09ecc18abcc5972f65938ba8607dfeede026 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -259,7 +259,11 @@ public class Commands {
TimeCommand.register(this.dispatcher);
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ // Lophine start - unsafe waypoint bar
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) {
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ }
+ // Lophine end - unsafe waypoint bar
WeatherCommand.register(this.dispatcher);
WorldBorderCommand.register(this.dispatcher);
if (JvmProfiler.INSTANCE.isAvailable()) {
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254b9b656d7 100644
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
@@ -22,7 +22,14 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
@Override
public void trackWaypoint(WaypointTransmitter waypoint) {
- // Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.waypoints.add(waypoint);
+
+ for (ServerPlayer serverPlayer : this.players) {
+ this.createConnection(serverPlayer, waypoint);
+ }
+ // Lophine end - unsafe waypoint bar
}
@Override
@@ -50,14 +57,48 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
public void addPlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.players.add(player);
+
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
+ this.createConnection(player, waypointTransmitter);
+ }
+
+ if (player.isTransmittingWaypoint()) {
+ this.trackWaypoint((WaypointTransmitter)player);
+ }
+ // Lophine end - unsafe waypoint bar
}
public void updatePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.row(player);
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
+
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
+ this.updateConnection(player, entry.getKey(), entry.getValue());
+ }
+
+ for (WaypointTransmitter waypointTransmitter : set) {
+ this.createConnection(player, waypointTransmitter);
+ }
+ // Lophine end - unsafe waypoint bar
}
public void removePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ this.connections.row(player).values().removeIf(connection -> {
+ connection.disconnect();
+ return true;
+ });
+ this.untrackWaypoint((WaypointTransmitter)player);
+ this.players.remove(player);
+ // Lophine end - unsafe waypoint bar
}
public void breakAllConnections() {
@@ -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/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 8405157ec35a443e238fa6866772c839621d73d7..67f3454e6479abb241a7d94699d4f7bec22da56b 100644
index 80b5d151e0dd6fa44794187875b4b80519839d81..8d32d906f87a1cb866a7497ee0de3045e9adce2c 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -334,6 +334,8 @@ public final class RegionizedServer {
@@ -369,6 +369,8 @@ public final class RegionizedServer {
}
// Luminol end - Add a config to enable tick command
@@ -21,7 +21,7 @@ index 8405157ec35a443e238fa6866772c839621d73d7..67f3454e6479abb241a7d94699d4f7be
this.tickConnections();
diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644
index 1da034752064312962a4144f91be5265a9a08997..081ca42b6a6644eb8c2b5ac9105fecf8ad39d501 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 {
@@ -39,20 +39,20 @@ index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f93
@Override
public CustomPacketPayload decode(B buffer) {
ResourceLocation resourceLocation = buffer.readResourceLocation();
- return (CustomPacketPayload)this.findCodec(resourceLocation).decode(buffer);
Identifier identifier = buffer.readIdentifier();
- return (CustomPacketPayload)this.findCodec(identifier).decode(buffer);
+ // Leaves start - protocol core
+ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(resourceLocation, buffer);
+ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(resourceLocation).decode(buffer));
+ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(identifier, buffer);
+ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(identifier).decode(buffer));
+ // Leaves end - protocol core
}
};
}
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3ddc776bf9e 100644
index 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707678da7a3 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -57,6 +57,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -58,6 +58,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
public @Nullable String playerBrand;
public final java.util.Set<String> pluginMessagerChannels;
// Paper end - retain certain values
@@ -60,7 +60,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie) {
this.server = server;
@@ -70,6 +71,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -71,6 +72,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
this.pluginMessagerChannels = cookie.channels();
this.keepAlive = cookie.keepAlive();
// Paper end
@@ -68,7 +68,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
}
// Paper start - configuration phase API
@@ -160,6 +162,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -161,6 +163,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@Override
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
@@ -77,7 +77,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), leavesPayload);
+ return;
+ }
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.DiscardedPayload(net.minecraft.resources.ResourceLocation id, byte[] data)) {
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.DiscardedPayload(net.minecraft.resources.Identifier id, byte[] data)) {
+ if (org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleBytebuf(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), id, io.netty.buffer.Unpooled.wrappedBuffer(data))) {
+ return;
+ }
@@ -87,7 +87,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
// Paper start
if (!(packet.payload() instanceof final net.minecraft.network.protocol.common.custom.DiscardedPayload discardedPayload)) {
return;
@@ -219,10 +233,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -220,10 +234,11 @@ 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);
@@ -100,7 +100,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
}
@Override
@@ -385,9 +400,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -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(
@@ -113,7 +113,7 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
);
@@ -420,10 +435,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@@ -421,10 +436,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
private void disconnect0(DisconnectionDetails disconnectionDetails) {
this.connection
@@ -129,27 +129,27 @@ index 8150b16c196edcb226be9268ea6e0012e44517fa..c54bf0429c0ca3a35a730658c7b1b3dd
this.connection.setReadOnly();
// CraftBukkit - Don't wait
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 4ef2816210f06082f2209c51d04aad6bb188232b..593dbcda4b497291eb1ecdc64b947a8d279f8be6 100644
index d2b2bf35b3f5704f3bca94d0fe3b70206c2fbf96..c8be04b8a50bac52150a1fdd238634e630e1765e 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -423,6 +423,8 @@ public abstract class PlayerList {
//return; // Folia - region threading - must still allow the player to connect, as we must add to chunk map before handling disconnect
}
@@ -315,6 +315,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);
+
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -605,6 +607,7 @@ public abstract class PlayerList {
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -511,6 +513,7 @@ public abstract class PlayerList {
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
}
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
public net.kyori.adventure.text.@Nullable Component remove(ServerPlayer player, 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();
player.awardStat(Stats.LEAVE_GAME);
@@ -1520,6 +1523,7 @@ public abstract class PlayerList {
@@ -1401,6 +1404,7 @@ public abstract class PlayerList {
serverPlayer.connection.send(clientboundUpdateRecipesPacket);
serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer);
}
@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 29 Oct 2025 00:09:09 +0800
Subject: [PATCH] Leaves: Configurable trading with the void
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index d0b5bc9da450d881534abdbd8ff786e1fbc7d418..674450fb2e600236f99550febf276d093308b8d8 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
// Spigot start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start - Fix merchant inventory not closing on entity removal
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Leaves - Configurable trading with the void
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
}
// Paper end - Fix merchant inventory not closing on entity removal
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index c8be04b8a50bac52150a1fdd238634e630e1765e..2eb551390aa66d89988df9ca23cf0dd7ccfd6577 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -555,7 +555,7 @@ public abstract class PlayerList {
player.stopRiding();
rootVehicle.getPassengersAndSelf().forEach(entity -> {
// Paper start - Fix villager boat exploit
- if (entity instanceof net.minecraft.world.entity.npc.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
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
--- a/net/minecraft/world/inventory/MerchantMenu.java
+++ b/net/minecraft/world/inventory/MerchantMenu.java
@@ -74,6 +74,7 @@ public class MerchantMenu extends AbstractContainerMenu {
@Override
public boolean stillValid(Player player) {
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade) return this.trader.getTradingPlayer() == player; // Leaves - Configurable trading with the void
if (!checkReachable) return true; // Paper - checkReachable
return this.trader.stillValid(player);
}
@@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 28 Sep 2025 13:21:30 +0800
Subject: [PATCH] Rewrite tickCount support
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index b957585cf7cf7f845e20f59c7b355722880f3b4e..9b279d003eb9f780ed2723c98b28d9f4d6e3a281 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -412,6 +412,8 @@ public final class TickRegionScheduler {
}
// Luminol end - Add tick command support
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
+
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
throw new IllegalStateException("Scheduled region should be acquirable");
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index b156b5c635f931a3d4abc0584591f90476d011a6..ef0b401affa58077e8dd32b52063202a1c7e0bb6 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -305,6 +305,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - regionised ticking
public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer();
+ private int tickCount; // Lophine - reuse tick count
+ private int lastTickCount;
@Override
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
@@ -2227,9 +2229,25 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false;
}
+ // Lophine start - reuse tick count
public int getTickCount() {
- throw new UnsupportedOperationException(); // Folia - region threading
+ return tickCount;
+ }
+
+ public boolean checkTickCount(int period) {
+ if (tickCount % period == 0) {
+ return true;
+ }
+
+ int nextPeriodTick = ((lastTickCount / period) + 1) * period;
+ return nextPeriodTick < tickCount;
+ }
+
+ public void handleTickCount(int tickCount) {
+ this.lastTickCount = this.tickCount;
+ this.tickCount += tickCount;
}
+ // Lophine end - reuse tick count
public int getSpawnProtectionRadius() {
return 16;
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/46cccfc39cafbca16
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
index 643797124fe5a4489d0b7419b7e600c04f283ef2..04b4100da96aad50f08e8c59200eec934e7e873d 100644
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 {
@@ -28,23 +28,23 @@ index 643797124fe5a4489d0b7419b7e600c04f283ef2..04b4100da96aad50f08e8c59200eec93
public String serialize(HolderLookup.Provider levelRegistry) {
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
index 7ef109cb9921c25987905149616eddbd0b2f9b9c..70fc9d6c5b226211ff5964464c37e11695d5f745 100644
index 1281eadb2d0c5b4ce5e3afd51d8205f9a4ef011c..b1446dfb4689174ee9f55cec6080622ec34de250 100644
--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -55,7 +55,7 @@ public class GiveCommand {
@@ -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);
final Component displayName = itemStack.getDisplayName(); // Paper - get display name early
- int maxStackSize = itemStack.getMaxStackSize();
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
int i = maxStackSize * 100;
if (count > i) {
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName()));
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c869690321c67f 100644
index 6d0bb9868e2c2ef516de7630442808c04ba47b39..1a749d9bee139975fa249839df93c3a1e48bf102 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3079,7 +3079,7 @@ public class ServerGamePacketListenerImpl
@@ -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;
@@ -53,7 +53,7 @@ index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c86969
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
if (toPlace == 1) {
action = InventoryAction.PLACE_ONE;
@@ -3115,7 +3115,7 @@ public class ServerGamePacketListenerImpl
@@ -3198,7 +3198,7 @@ public class ServerGamePacketListenerImpl
}
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
if (clickedItem.getCount() >= 0) {
@@ -62,7 +62,7 @@ index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c86969
// As of 1.5, this is result slots only
action = InventoryAction.PICKUP_ALL;
}
@@ -3326,6 +3326,7 @@ public class ServerGamePacketListenerImpl
@@ -3415,6 +3415,7 @@ public class ServerGamePacketListenerImpl
this.player.containerMenu.broadcastFullState();
} else {
this.player.containerMenu.broadcastChanges();
@@ -70,7 +70,7 @@ index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c86969
}
if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
@@ -3437,7 +3438,7 @@ public class ServerGamePacketListenerImpl
@@ -3526,7 +3527,7 @@ public class ServerGamePacketListenerImpl
}
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
@@ -79,7 +79,7 @@ index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c86969
if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
// CraftBukkit start - Call click event
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
@@ -3479,6 +3480,7 @@ public class ServerGamePacketListenerImpl
@@ -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();
@@ -88,10 +88,10 @@ index 74ec003486f9362d2bafbad8392b9bbdf0c15882..f06b9d8ad9512d35f3f460eb77c86969
} else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) {
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
index 2afaf6a3f18af7889f4f3b35cee9bbb5e4ec01f2..da99b4bc7fe8460945070915073be141f9bd6778 100644
index b63cecafd841b97a694f6d2610141dcdb8f30574..392678778dc2a036c1e3db4b6bb2800e452d3cd0 100644
--- a/net/minecraft/world/Container.java
+++ b/net/minecraft/world/Container.java
@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable<ItemStack>, org.leavesmc.
@@ -37,6 +37,12 @@ public interface Container extends Clearable, SlotProvider, Iterable<ItemStack>,
return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
}
@@ -105,10 +105,10 @@ index 2afaf6a3f18af7889f4f3b35cee9bbb5e4ec01f2..da99b4bc7fe8460945070915073be141
boolean stillValid(Player player);
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab630b0e54e 100644
index 0233c2b5e40c33330870e598431897a2ff98c2a3..3cf1819a9c82da2d2e0c43187e204353e3643369 100644
--- a/net/minecraft/world/SimpleContainer.java
+++ b/net/minecraft/world/SimpleContainer.java
@@ -211,7 +211,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
@@ -210,7 +210,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
@Override
public void setItem(int index, ItemStack stack) {
this.items.set(index, stack);
@@ -117,7 +117,7 @@ index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab6
this.setChanged();
}
@@ -286,7 +286,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
@@ -285,7 +285,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
}
private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) {
@@ -127,10 +127,10 @@ index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab6
if (min > 0) {
other.grow(min);
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index fd4f1e63f980b6959fc80084651991f8f8bc6c34..e5e8c752129a6ebb0dd1315c9b8ec459be11ef07 100644
index 16c42a5e35c6ee1df640e5831818099fab6338f1..f3f067c62dc024a747d059608ae7a2e8740dbff2 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -283,10 +283,15 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
@@ -271,10 +271,15 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
private boolean isMergable() {
ItemStack item = this.getItem();
@@ -148,10 +148,10 @@ index fd4f1e63f980b6959fc80084651991f8f8bc6c34..e5e8c752129a6ebb0dd1315c9b8ec459
ItemStack item1 = itemEntity.getItem();
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0c59f7654 100644
index 41e59f3739945ca7f6ab710c993b5c0f15fcd529..b849b04f227b43d036f4f6b3ae7accfafc389d9f 100644
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -165,10 +165,12 @@ public class Inventory implements Container, Nameable {
@@ -166,10 +166,12 @@ public class Inventory implements Container, Nameable {
}
private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) {
@@ -166,7 +166,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0
}
// CraftBukkit start - Watch method above! :D
@@ -181,7 +183,7 @@ public class Inventory implements Container, Nameable {
@@ -182,7 +184,7 @@ public class Inventory implements Container, Nameable {
}
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
@@ -175,7 +175,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0
}
if (remains <= 0) {
return itemStack.getCount();
@@ -190,7 +192,7 @@ public class Inventory implements Container, Nameable {
@@ -191,7 +193,7 @@ public class Inventory implements Container, Nameable {
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
@@ -184,7 +184,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0
}
if (remains <= 0) {
return itemStack.getCount();
@@ -314,7 +316,7 @@ public class Inventory implements Container, Nameable {
@@ -315,7 +317,7 @@ public class Inventory implements Container, Nameable {
this.setItem(slot, item);
}
@@ -193,7 +193,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0
int min = Math.min(count, i);
if (min == 0) {
return count;
@@ -420,7 +422,7 @@ public class Inventory implements Container, Nameable {
@@ -421,7 +423,7 @@ public class Inventory implements Container, Nameable {
break;
}
@@ -203,10 +203,10 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0
serverPlayer.connection.send(this.createInventoryUpdatePacket(slotWithRemainingSpace));
}
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
index 83ccde54c625d40dc595e000c533f60aa929bd5a..6779503888e6d311758cffde582b0efbd66a33de 100644
index 00dbc0d125b2c8c208ffa46f9084c6317efaba90..1f57b3c60fd0cbfdd65e06f8994525ade6dc6bd9 100644
--- a/net/minecraft/world/entity/player/StackedItemContents.java
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
@@ -23,7 +23,7 @@ public class StackedItemContents {
@@ -36,7 +36,7 @@ public class StackedItemContents {
}
public void accountStack(ItemStack stack) {
@@ -216,10 +216,10 @@ index 83ccde54c625d40dc595e000c533f60aa929bd5a..6779503888e6d311758cffde582b0efb
public void accountStack(ItemStack stack, int maxStackSize) {
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a76381cee 100644
index 44276ba9c7aab306cfd12833a834ebe61cf64e7c..0a19a7782f3fa27c41e02393e887ba7cc727012b 100644
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
@@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider {
@@ -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);
@@ -227,12 +227,12 @@ index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
}
default SlotAccess getChestVehicleSlot(final int index) {
default @Nullable SlotAccess getChestVehicleSlot(final int slot) {
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121ba48625a 100644
index 3b1c6a2397950ceb167890961b635cc69aaf8950..e7ea8849e8fa942709f505145e8076f064476206 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -295,6 +295,13 @@ public abstract class AbstractContainerMenu {
@@ -292,6 +292,13 @@ public abstract class AbstractContainerMenu {
this.sendAllDataToRemote();
}
@@ -246,7 +246,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
private void updateDataSlotListeners(int slotIndex, int value) {
for (ContainerListener containerListener : this.containerListeners) {
containerListener.dataChanged(this, slotIndex, value);
@@ -451,7 +458,7 @@ public abstract class AbstractContainerMenu {
@@ -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;
@@ -255,7 +255,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min);
count -= min1 - i2;
// slot1.setByPlayer(itemStack.copyWithCount(min1));
@@ -563,7 +570,7 @@ public abstract class AbstractContainerMenu {
@@ -556,7 +563,7 @@ public abstract class AbstractContainerMenu {
slot.setByPlayer(carried2);
}
} else if (ItemStack.isSameItemSameComponents(carried, carried2)) {
@@ -264,16 +264,16 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
optional1.ifPresent(itemStack2 -> {
carried2.grow(itemStack2.getCount());
slot.onTake(player, itemStack2);
@@ -625,7 +632,7 @@ public abstract class AbstractContainerMenu {
Slot slot2 = this.slots.get(slotId);
@@ -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() && slotId >= 0) {
Slot slot2 = this.slots.get(slotId);
@@ -660,15 +667,15 @@ public abstract class AbstractContainerMenu {
} 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++) {
@@ -292,7 +292,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
itemStack.grow(itemStack1.getCount());
}
}
@@ -770,7 +777,7 @@ public abstract class AbstractContainerMenu {
@@ -763,7 +770,7 @@ public abstract class AbstractContainerMenu {
i = endIndex - 1;
}
@@ -301,7 +301,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) {
Slot slot = this.slots.get(i);
ItemStack item = slot.getItem();
@@ -871,7 +878,7 @@ public abstract class AbstractContainerMenu {
@@ -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())
@@ -310,7 +310,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
: flag;
}
@@ -879,7 +886,7 @@ public abstract class AbstractContainerMenu {
@@ -872,7 +879,7 @@ public abstract class AbstractContainerMenu {
return switch (type) {
case 0 -> Mth.floor((float)stack.getCount() / slots.size());
case 1 -> 1;
@@ -319,7 +319,7 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
default -> stack.getCount();
};
}
@@ -902,7 +909,7 @@ public abstract class AbstractContainerMenu {
@@ -895,7 +902,7 @@ public abstract class AbstractContainerMenu {
for (int i = 0; i < container.getContainerSize(); i++) {
ItemStack item = container.getItem(i);
if (!item.isEmpty()) {
@@ -329,10 +329,10 @@ index 2d6acceffb2cb7e55dd504018a70b05afccd9c11..bdc0ca1f625dc264bef6e5722ec66121
}
diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java
index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..1a593d5bfc4574fd071604105422cd1d395648b8 100644
index a4203c416c7a83557055099a9ea8f43ac2b18b21..46c8026876e851ec4a31fd34c9b64623469ffb8d 100644
--- a/net/minecraft/world/inventory/MerchantContainer.java
+++ b/net/minecraft/world/inventory/MerchantContainer.java
@@ -109,7 +109,7 @@ public class MerchantContainer implements Container {
@@ -108,7 +108,7 @@ public class MerchantContainer implements Container {
@Override
public void setItem(int index, ItemStack stack) {
this.itemStacks.set(index, stack);
@@ -342,7 +342,7 @@ index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..1a593d5bfc4574fd071604105422cd1d
this.updateSellItem();
}
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
index 5ceb8964476b40db4511bec91ff13c4f522a1357..f416d7976e41a06b5a8be93485eaa233ffceda5c 100644
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 {
@@ -353,21 +353,21 @@ index 5ceb8964476b40db4511bec91ff13c4f522a1357..f416d7976e41a06b5a8be93485eaa233
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack)); // Leaves - item over-stack util
}
@Nullable
public @Nullable Identifier getNoItemIcon() {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index 33c3a5e39e8e1aa023baab76ef94f8aed481480e..a27e1d53abc2d8b8912226add33510067e10ed52 100644
index ed2971b54afbebe37a7ff61798778a4249b79856..73a97f4f62fe7d27b441cab58c6c86ffce011060 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -166,7 +166,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -174,7 +174,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
private int popTime;
@Deprecated
@Nullable
private Item item;
private @Nullable Item item;
- PatchedDataComponentMap components;
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
@Nullable
private Entity entityRepresentation;
private @Nullable Entity entityRepresentation;
@@ -193,7 +193,8 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
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);
@@ -377,7 +377,7 @@ index 33c3a5e39e8e1aa023baab76ef94f8aed481480e..a27e1d53abc2d8b8912226add3351006
}
}
@@ -202,13 +203,15 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -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 {
@@ -397,7 +397,7 @@ index 33c3a5e39e8e1aa023baab76ef94f8aed481480e..a27e1d53abc2d8b8912226add3351006
} finally {
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
}
@@ -303,7 +306,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -309,7 +312,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) {
int count = itemStack.getCount();
@@ -407,10 +407,10 @@ index 33c3a5e39e8e1aa023baab76ef94f8aed481480e..a27e1d53abc2d8b8912226add3351006
return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize);
}
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8c8a1e5d1 100644
index c5fe15844d405a27cdae18c903dd481c25b437de..3faa541c4a4623e915269d6241e1a3a3c6e374ff 100644
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -192,7 +192,7 @@ public class CrafterBlock extends BaseEntityBlock {
@@ -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();
@@ -420,10 +420,10 @@ index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index d7a211220d5eba7e34b9083f06f39e9527962599..cef2d6d9a42ae36d6e2a0b31685a7738d2a400cf 100644
index 9346f2deca8eeca29fa2fced416247fd1609249e..07236e86638faa3231917af507cdd37ac49b1270 100644
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -411,7 +411,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
@@ -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);
@@ -433,10 +433,10 @@ index d7a211220d5eba7e34b9083f06f39e9527962599..cef2d6d9a42ae36d6e2a0b31685a7738
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
this.cookingTimer = 0;
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b8f75c253 100644
index 8f80c469c309bf61328c4f98037495f47a38c3c1..b4127d4b4386b98205275a9a0ef8067ccf287e67 100644
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -155,7 +155,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
@@ -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);
@@ -446,10 +446,10 @@ index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b
}
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b64e4409b0 100644
index f851e0f7d727cb9dca70c578777d871af424388c..6a51bace3151646afae9de820d9c8977a0221df4 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -148,7 +148,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -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);
@@ -458,7 +458,7 @@ index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b6
}
@Override
@@ -770,9 +770,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -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
@@ -469,4 +469,4 @@ index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b6
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
}
// Spigot end
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - Use vanilla hopper logic
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - vanilla hopper
@@ -8,14 +8,14 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e96b237749a960f2
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index b3e897a4afee742b5055d652ad7047a660d8ea04..33471f3d0e2cbd54eaf095c19555f8fdaeb55878 100644
index 08a1be57e1057a9e961eeb8f59cd12e98ed52bab..33ee967d8a7d4ce2c455db9ffaac740cd589e6f3 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -729,6 +729,7 @@ public class ServerExplosion implements Explosion {
@@ -717,6 +717,7 @@ public class ServerExplosion implements Explosion {
public boolean shouldAffectBlocklikeEntities() {
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
boolean flag = this.source == null || this.source.getType() != EntityType.BREEZE_WIND_CHARGE && this.source.getType() != EntityType.WIND_CHARGE;
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldExplosionDamageCalculator) flag = flag && (this.source == null || !this.source.isInWater()); // Leaves - Old MC TNT wet explosion no item damage
return _boolean ? flag : this.blockInteraction.shouldAffectBlocklikeEntities() && flag;
boolean 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;
}
@@ -24,10 +24,10 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..c9af615ff9120c07787f436dbb6024e5
if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) {
serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier));
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34320a4fa2 100644
index dcdd6f230ff153a7b58d13b963d32376b1905b72..be9c78f2cf121e8ae55c1b18685877637a25ec80 100644
--- a/net/minecraft/world/entity/raid/Raid.java
+++ b/net/minecraft/world/entity/raid/Raid.java
@@ -263,7 +263,7 @@ public class Raid {
@@ -264,7 +264,7 @@ public class Raid {
}
public boolean absorbRaidOmen(ServerPlayer player) {
@@ -36,7 +36,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
if (effect == null) {
return false;
} else {
@@ -340,7 +340,13 @@ public class Raid {
@@ -341,7 +341,13 @@ public class Raid {
}
if (flag1) {
@@ -51,7 +51,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
}
if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) {
@@ -375,7 +381,14 @@ public class Raid {
@@ -396,7 +402,14 @@ public class Raid {
int i = 0;
while (this.shouldSpawnGroup()) {
@@ -67,7 +67,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
if (blockPos != null) {
this.started = true;
this.spawnGroup(level, blockPos);
@@ -387,7 +400,7 @@ public class Raid {
@@ -408,7 +421,7 @@ public class Raid {
i++;
}
@@ -76,7 +76,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
this.stop();
break;
@@ -683,7 +696,7 @@ public class Raid {
@@ -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);
@@ -85,7 +85,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
mutableBlockPos.set(i2, height, i3);
if (!level.isVillage(mutableBlockPos) || i <= 7) {
int i4 = 10;
@@ -702,6 +715,36 @@ public class Raid {
@@ -721,6 +734,36 @@ public class Raid {
return null;
}
@@ -122,7 +122,7 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
private boolean addWaveMob(ServerLevel level, int wave, Raider raider) {
// Folia start - make raids thread-safe
if (!this.ownsRaid(level)) {
@@ -864,4 +907,43 @@ public class Raid {
@@ -883,4 +926,43 @@ public class Raid {
this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus;
}
}
@@ -167,10 +167,10 @@ index 1910bff3f08147bfd63703097e30b9f88c84e337..f45aa44a7a17946aeb406a447f18de34
+ // Leaves end - old FindSpawnPosition
}
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..2d163f3d5eb1af4d539d24c0256855bbec960de4 100644
index 5e8245e6dd8a07ece83dd1bc20e351a92044e7a0..2b7894a4104d4cb237746a3e66d4368b6f8f3c1e 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -128,6 +128,43 @@ public abstract class Raider extends PatrollingMonster {
@@ -127,6 +127,43 @@ public abstract class Raider extends PatrollingMonster {
currentRaid.removeFromRaid(serverLevel, this, false);
}
@@ -203,7 +203,7 @@ index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..2d163f3d5eb1af4d539d24c0256855bb
+ i = net.minecraft.util.Mth.clamp(i, 0, 4);
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, i, false, false, true);
+
+ if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
+ 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);
@@ -213,4 +213,4 @@ index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..2d163f3d5eb1af4d539d24c0256855bb
+ // Leaves end - Revert raid changes
}
super.die(cause);
super.die(damageSource);
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/79d9ef74c2684eb49
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
index 8cf3e51e12f9cf98836657e722edb23943f9e866..5fd5e9fd4e1a79dd1a9d62a5cf0c308805979420 100644
index 5e25ddf78f72ada318ef28d29199de9b93fe667e..6f48162a25e20d2439935e8995cede9497626322 100644
--- a/net/minecraft/world/item/ShearsItem.java
+++ b/net/minecraft/world/item/ShearsItem.java
@@ -80,7 +80,10 @@ public class ShearsItem extends Item {
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335ec643957f 100644
index 95f6b1cbd5e33151c326689bc72292ff38a48803..e1974bbebbd10b75ea02955d9ced198d54c8a6f1 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -134,4 +134,10 @@ public class ServerTickRateManager extends TickRateManager {
@@ -135,4 +135,10 @@ public class ServerTickRateManager extends TickRateManager {
player.connection.send(ClientboundTickingStatePacket.from(this));
player.connection.send(ClientboundTickingStepPacket.from(this));
}
@@ -23,14 +23,15 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
+ // Leaves end - servux
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index eb3aef1f5198592eda5dafe84b91271e861b4135..576dde41a4b48aac9079cca902f4371a31470af3 100644
index 674450fb2e600236f99550febf276d093308b8d8..f5bf8ed6e741823078ab93eac47636fcebcdfe2d 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2463,6 +2463,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.server.updateEffectiveRespawnData();
}
this.lastSpawnChunkRadius = i;
// Paper end
+
+ org.leavesmc.leaves.protocol.servux.ServuxHudDataProtocol.refreshSpawnMetadata = true; // Leaves - servux
}
public LongSet getForceLoadedChunks() {
@Override
@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 16 Nov 2025 17:47:48 +0800
Subject: [PATCH] LeavesHooks
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
index faf62f8c9453f8e7a21b1e141577f1f4539cd2f9..4e5985a3e4969f466980558190324350019ba8af 100644
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB;
import java.util.List;
import java.util.function.Predicate;
-public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
+public class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
@@ -6,10 +6,10 @@ Subject: [PATCH] Compatibility fix for Raid Revert and Cross Region Damage
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index e94687b3aa960f9c630f459fedc17bc01846eaf7..f4f4f886b6558d39d292a45665953f497f84be53 100644
index 5bae274f5ee869e540e4330e03af671b6b18313d..3fe9afe55b4d61db8030479d3d74b8656679cb10 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1216,6 +1216,29 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -1240,6 +1240,29 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
}
@@ -40,13 +40,13 @@ index e94687b3aa960f9c630f459fedc17bc01846eaf7..f4f4f886b6558d39d292a45665953f49
if (this.getType().is(EntityTypeTags.IMMUNE_TO_INFESTED)) {
return !effectInstance.is(MobEffects.INFESTED);
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
index 2d163f3d5eb1af4d539d24c0256855bbec960de4..2cc0a7b5f088c29d9343b369b6e71c8a3ebdef75 100644
index 2b7894a4104d4cb237746a3e66d4368b6f8f3c1e..03e3290367790add702a5856aaff3be465ea548c 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -158,7 +158,7 @@ public abstract class Raider extends PatrollingMonster {
@@ -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);
if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
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
}
@@ -8,10 +8,10 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b9764c051 100644
index 2eb551390aa66d89988df9ca23cf0dd7ccfd6577..0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1087,6 +1087,10 @@ public abstract class PlayerList {
@@ -963,6 +963,10 @@ public abstract class PlayerList {
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
} // Paper - Add sendOpLevel API
@@ -23,10 +23,10 @@ index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b
// Paper start - whitelist verify event / login event
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 09b549fa9568aa1ae13b1b975db14a6268fdaa46..6c933c27ce155eb516a9ede96fb2c3bd19251bfa 100644
index 0f6e1428cc71c370af45db3e2a4f47c66e5d8628..83612969b6058f444fc17e360cdcc4a8846f79aa 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -219,6 +219,7 @@ public abstract class Player extends LivingEntity {
@@ -179,6 +179,7 @@ public abstract class Player extends Avatar implements ContainerUser {
private int currentImpulseContextResetGraceTime = 0;
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
@@ -35,7 +35,7 @@ index 09b549fa9568aa1ae13b1b975db14a6268fdaa46..6c933c27ce155eb516a9ede96fb2c3bd
// CraftBukkit start
public boolean fauxSleeping;
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
index 0fffa384f928ab84451331380968fb4650eafe26..d84a10396395939149da88bcb01be59e220c340e 100644
index 1fb3a34ea872dec73658fac59743e46ef8db5151..41ebe774edfe3c37afecda514a6eb7db978d5aa8 100644
--- a/net/minecraft/world/inventory/ChestMenu.java
+++ b/net/minecraft/world/inventory/ChestMenu.java
@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu {
@@ -70,7 +70,7 @@ index 0fffa384f928ab84451331380968fb4650eafe26..d84a10396395939149da88bcb01be59e
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6);
}
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
index 51148b7b95c93a9e25da70ac9275c63f1458d84c..dba8acfcacfe9a7b7e0fb9943fba49468214616e 100644
index 9749909b8253b432bb2f7fba2cd8ff17a8579b30..42df617d7b62af45bd56e9594689974f790f6c19 100644
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
@@ -26,11 +26,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
@@ -94,7 +94,7 @@ index 51148b7b95c93a9e25da70ac9275c63f1458d84c..dba8acfcacfe9a7b7e0fb9943fba4946
this.activeChest = enderChestBlockEntity;
}
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..cef29289b7bc7fdf9613c0cd52f2bf4f715f288d 100644
index 383e8285d366c7f594b0b4ff55b367970c9b69e4..202a986762794da9440365953fcb950c6eefa774 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
@@ -115,13 +115,13 @@ index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..cef29289b7bc7fdf9613c0cd52f2bf4f
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
player.awardStat(Stats.OPEN_ENDERCHEST);
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495ebd87b5f 100644
index dcec63c1c2634a3e83ee3cac26f6e51441c37f6d..e5cfbf41525b0d454bb83691354afb4513723571 100644
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -56,7 +56,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -59,7 +59,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
}
// CraftBukkit end
private static final Component DEFAULT_NAME = Component.translatable("container.barrel");
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
+ // Purpur start - Barrels and enderchests 6 rows
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
@@ -137,7 +137,7 @@ index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
@Override
protected void onOpen(Level level, BlockPos pos, BlockState state) {
@@ -108,7 +118,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -111,7 +121,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
@Override
public int getContainerSize() {
@@ -155,7 +155,7 @@ index de99652629c7301a4bc0e9ec48bed9a26a338f0d..b43445d8313c330a0376aaa4eb872495
}
@Override
@@ -129,7 +148,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -132,7 +151,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
@Override
protected AbstractContainerMenu createMenu(int id, Inventory player) {
@@ -5,10 +5,18 @@ Subject: [PATCH] I18n support
diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java
index 7b9e2a1a208b46a69c16e6afd8b502259893574f..db46a31ea8a36562e548eb07f0c4cf9b9e8c3360 100644
index 7b9e2a1a208b46a69c16e6afd8b502259893574f..c300ae4363298fecef8fa9bf739f01c0a11e145f 100644
--- a/net/minecraft/locale/Language.java
+++ b/net/minecraft/locale/Language.java
@@ -65,7 +65,7 @@ public abstract class Language {
@@ -36,6 +36,7 @@ public abstract class Language {
Map<String, String> map = new HashMap<>();
BiConsumer<String, String> biConsumer = map::put;
parseTranslations(biConsumer, "/assets/minecraft/lang/en_us.json");
+ fun.bm.lophine.utils.ServerI18nUtil.loadLophineI18nDefault(biConsumer);
deprecatedTranslationsInfo.applyToMap(map);
final Map<String, String> map1 = Map.copyOf(map);
return new Language() {
@@ -65,7 +66,7 @@ public abstract class Language {
};
}
@@ -18,10 +26,10 @@ index 7b9e2a1a208b46a69c16e6afd8b502259893574f..db46a31ea8a36562e548eb07f0c4cf9b
loadFromJson(resourceAsStream, output);
} catch (JsonParseException | IOException var7) {
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442dad2db19b 100644
index f41c70c6cb2e9fae43bad9dd66546417fe38f14a..0bb0877011cac3184b881bfa35f10ef83d7341de 100644
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -155,6 +155,8 @@ public class Main {
@@ -151,6 +151,8 @@ public class Main {
return;
}
@@ -31,10 +39,10 @@ index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442d
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
if (awtException != null) {
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index c93feb64b6088a4878fcdb6e7c733a5f37e9385b..79c911003c7b1c3d94e7e9d3974eeadcc16bde3a 100644
index 4abfcaae4fe024296961987704e2a11a03ee518b..5fbcb5eac1d5449247da77b6120edbe2f2dd1d58 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -262,6 +262,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
@@ -4,11 +4,11 @@ Date: Mon, 19 May 2025 00:42:17 +0800
Subject: [PATCH] Old zombie reinforcement
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
index 14d0758aca54d9a25e369dfa8c89c930f27946c9..1324f2c8c0d6571bac36855f08354a84e0f08b70 100644
--- a/net/minecraft/world/entity/monster/Zombie.java
+++ b/net/minecraft/world/entity/monster/Zombie.java
@@ -341,7 +341,7 @@ public class Zombie extends Monster {
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
index 7a9394d4555464312418964f1a7a5d2581496774..3fcd32cc77458ce196ce0e468c1a99f456a57604 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());
@@ -5,26 +5,26 @@ Subject: [PATCH] Spawn invulnerable time
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index de1263404395c28209234a556347284fa557f81c..44f0e3a675c612e9ca2bc40cc3898bdbca0f6718 100644
index ec34282744c71c881392ff278a8b03af90de8151..f0d45cb70af62b747c9235941f3fc45221b3b8e6 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -232,6 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -240,6 +240,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private int lastSentFood = -99999999;
private boolean lastFoodSaturationZero = true;
public int lastSentExp = -99999999;
+ private int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
+ protected int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
public ParticleStatus particleStatus = ParticleStatus.ALL;
private boolean canChatColor = true;
@@ -925,6 +926,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.tickClientLoadTimeout();
@@ -898,6 +899,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.connection.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
+ if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
if (this.invulnerableTime > 0) {
this.invulnerableTime--;
}
@@ -1435,6 +1437,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1536,6 +1538,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
@@ -1,16 +1,16 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 30 Aug 2025 17:16:32 +0800
Subject: [PATCH] Leaves: Leaves Fakeplayer
Subject: [PATCH] Leaves: Fakeplayer
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c96afb491c 100644
--- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
+++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
diff --git a/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java b/net/minecraft/advancements/criterion/SimpleCriterionTrigger.java
index 368a9d33f93c2e85abe4cf10df5a85c09fb03dd6..2b78040daeb3b09c08494cbc1d4a9d36080895f9 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
}
@@ -20,23 +20,23 @@ index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c9
Set<CriterionTrigger.Listener<T>> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
if (set != null && !set.isEmpty()) {
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4beca0969 100644
index 9f444988d40208a1bfa9f147ef80489f81115e93..ab2fa0b86564622501238305714fff014e2b2a56 100644
--- a/net/minecraft/network/Connection.java
+++ b/net/minecraft/network/Connection.java
@@ -96,7 +96,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@Nullable
private volatile PacketListener disconnectListener;
@Nullable
- private volatile PacketListener packetListener;
+ protected volatile PacketListener packetListener; // Leaves - private -> protected
@Nullable
private DisconnectionDetails disconnectionDetails;
@@ -74,7 +74,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public boolean preparing = true;
// Spigot end
private volatile @Nullable PacketListener disconnectListener;
- private volatile @Nullable PacketListener packetListener;
+ public volatile @Nullable PacketListener packetListener; // Leaves - private -> protected // Lophine protected -> public
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 ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f9cf6d336 100644
index 8d96d2130cf3383427047fee97fa49155164e337..dfcf8eb7dc422a55d94d6eb9eb1451c7c14a1d56 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -349,6 +349,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -425,6 +425,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Folia end - regionised ticking
@@ -45,7 +45,7 @@ index ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
AtomicReference<S> atomicReference = new AtomicReference<>();
@@ -1040,6 +1042,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1050,6 +1052,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia end - region threading
public void stopServer() {
@@ -57,8 +57,8 @@ index ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f
// Folia start - region threading
// halt scheduler
// don't wait, we may be on a scheduler thread
@@ -1590,7 +1597,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = this.pauseWhileEmptySeconds() * 20;
@@ -1668,7 +1675,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = 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 (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping
@@ -66,7 +66,15 @@ index ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1914,6 +1921,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1801,6 +1808,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
public void tickConnection() {
this.getConnection().tick();
@@ -74,8 +82,8 @@ index ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f
}
private void synchronizeTime(ServerLevel level) {
@@ -3001,6 +3009,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return 0;
@@ -3155,6 +3164,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.debugSubscribers;
}
+ // Leaves start - fakeplayer
@@ -92,10 +100,10 @@ index ef0b401affa58077e8dd32b52063202a1c7e0bb6..c461ab6c6ab21008be893f84913f0e6f
@Override
public void close() {
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
index fdeca41d40705f28864ce4443d01cd872c9d51b0..5c0e338dc1b0eb5724d10a73d6fc7975f9d2e5e5 100644
index c9e6cd428e4c74b14a992de9ffe85a5a707c4e6b..5bf7eb5b906cefa57a1dfcf828ff7872dbceac4f 100644
--- a/net/minecraft/server/PlayerAdvancements.java
+++ b/net/minecraft/server/PlayerAdvancements.java
@@ -167,6 +167,11 @@ public class PlayerAdvancements {
@@ -166,6 +166,11 @@ public class PlayerAdvancements {
}
public boolean award(AdvancementHolder advancement, String criterionKey) {
@@ -108,7 +116,7 @@ index fdeca41d40705f28864ce4443d01cd872c9d51b0..5c0e338dc1b0eb5724d10a73d6fc7975
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
boolean isDone = orStartProgress.isDone();
diff --git a/net/minecraft/server/commands/BanIpCommands.java b/net/minecraft/server/commands/BanIpCommands.java
index bb5dbfeb6915a808d6f70e332bf9f0a3f9b7d19a..62f23d47b55eb59956d69153d508b5c9ab544adf 100644
index d92492bca62fb02fe7a9e4e220cb8651c4d1e16d..7d0752f9a6a90cf389a9cb5829ab02606266f204 100644
--- a/net/minecraft/server/commands/BanIpCommands.java
+++ b/net/minecraft/server/commands/BanIpCommands.java
@@ -44,6 +44,12 @@ public class BanIpCommands {
@@ -125,36 +133,26 @@ index bb5dbfeb6915a808d6f70e332bf9f0a3f9b7d19a..62f23d47b55eb59956d69153d508b5c9
return banIp(source, playerByName.getIpAddress(), reason);
} else {
diff --git a/net/minecraft/server/commands/BanPlayerCommands.java b/net/minecraft/server/commands/BanPlayerCommands.java
index ac3ba9d0ea344fa189912d359b718fbe05e7aa49..61a4db144f721b47ac1000df72263bceb6e38ec0 100644
index 978ef2e996a78e907f959bfe99d47de832427011..9644e68ba2c295fcda2d4a3034277520ade91bca 100644
--- a/net/minecraft/server/commands/BanPlayerCommands.java
+++ b/net/minecraft/server/commands/BanPlayerCommands.java
@@ -44,8 +44,16 @@ public class BanPlayerCommands {
private static int banPlayers(CommandSourceStack source, Collection<GameProfile> gameProfiles, @Nullable Component reason) throws CommandSyntaxException {
@@ -45,7 +45,15 @@ public class BanPlayerCommands {
UserBanList bans = source.getServer().getPlayerList().getBans();
int i = 0;
-
+ boolean hasBot = false; // Leaves - disable kick
for (GameProfile gameProfile : gameProfiles) {
for (NameAndId nameAndId : players) {
+ // Leaves start - disable ban
+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) {
+ if (nameAndId.isBot()) {
+ source.sendFailure(Component.literal("Permission denied"));
+ hasBot = true;
+ continue;
+ }
+ // Leaves end - disable ban
+ ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
if (!bans.isBanned(gameProfile)) {
if (!bans.isBanned(nameAndId)) {
UserBanListEntry userBanListEntry = new UserBanListEntry(
gameProfile, null, source.getTextName(), null, reason == null ? null : reason.getString()
@@ -55,7 +63,6 @@ public class BanPlayerCommands {
source.sendSuccess(
() -> Component.translatable("commands.ban.success", Component.literal(gameProfile.getName()), userBanListEntry.getReason()), true
);
- ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
if (player != null) {
player.connection.disconnect(Component.translatable("multiplayer.disconnect.banned"), org.bukkit.event.player.PlayerKickEvent.Cause.BANNED); // Paper - kick event cause
}
@@ -63,7 +70,13 @@ public class BanPlayerCommands {
nameAndId, null, source.getTextName(), null, reason == null ? null : reason.getString()
@@ -63,7 +71,13 @@ public class BanPlayerCommands {
}
if (i == 0) {
@@ -170,7 +168,7 @@ index ac3ba9d0ea344fa189912d359b718fbe05e7aa49..61a4db144f721b47ac1000df72263bce
return i;
}
diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java
index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88686b8785 100644
index 5f78d629bab84acb2fa43a9fcc1cec52b4e91ae3..1c6059bd23afdd555d2dc8c533a5b027957c7b3a 100644
--- a/net/minecraft/server/commands/KickCommand.java
+++ b/net/minecraft/server/commands/KickCommand.java
@@ -46,9 +46,17 @@ public class KickCommand {
@@ -188,7 +186,7 @@ index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88
+ continue;
+ }
+ // Leaves end - disable kick
if (!source.getServer().isSingleplayerOwner(serverPlayer.getGameProfile())) {
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 {
@@ -207,22 +205,22 @@ index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88
return i;
}
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
index f2286b96b8f40b4588f817913c42ae7b4a92340f..e6c7bbb023000b9de90c1256274ff5aba4a6478a 100644
index 07332a86e6e0441bafacb020f27ec36a277f1486..590891d70a71ab30ceae3a3cf1923745e7c20b26 100644
--- a/net/minecraft/server/commands/OpCommand.java
+++ b/net/minecraft/server/commands/OpCommand.java
@@ -43,6 +43,7 @@ public class OpCommand {
int i = 0;
for (GameProfile gameProfile : gameProfiles) {
+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) continue; // Leaves - disable op
if (!playerList.isOp(gameProfile)) {
playerList.op(gameProfile);
for (NameAndId nameAndId : players) {
+ if (nameAndId.isBot()) continue; // Leaves - disable op
if (!playerList.isOp(nameAndId)) {
playerList.op(nameAndId);
i++;
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f604b0d6890 100644
index 5fbcb5eac1d5449247da77b6120edbe2f2dd1d58..69cc67b7618d38e65ccb1f4c58013ef116886ad2 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -162,6 +162,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -252,6 +252,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
// Spigot start
@@ -230,31 +228,22 @@ index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f60
this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage));
org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings"));
org.spigotmc.SpigotConfig.registerCommands();
@@ -173,6 +174,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -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
+ this.getBotList().loadBotInfo(); // Leaves - load resident bot info
+ 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()) {
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348fcbaf9ded 100644
index fdccb06c918d387e46c29ede7337159db8c5d9ca..4cd5c5659ac098c3b7ff95efb94b1987e2dd40d0 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -134,7 +134,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public final AtomicInteger tickingGenerated = new AtomicInteger(); // Paper - public
private final String storageName;
//private final PlayerMap playerMap = new PlayerMap(); // Folia - region threading
- //public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
+ public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
private final Long2ByteMap chunkTypeCache = new Long2ByteOpenHashMap();
// Paper - rewrite chunk system
public int serverViewDistance;
@@ -1309,6 +1309,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1386,6 +1386,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
}
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
} else {
this.removePlayer(player);
+ // Leaves start - render bot
+ if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) {
+ if (bot.needSendFakeData(player)) {
@@ -266,18 +255,18 @@ index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348f
}
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6cf992049 100644
index f5bf8ed6e741823078ab93eac47636fcebcdfe2d..14516c3ebd092e6f230804145a60dc851f34230b 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -207,6 +207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
private final StructureCheck structureCheck;
@@ -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);
+ final List<ServerPlayer> realPlayers; // Leaves - skip
// CraftBukkit start
public final LevelStorageSource.LevelStorageAccess levelStorageAccess;
@@ -635,6 +636,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -669,6 +670,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - rewrite chunk system
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked
@@ -285,7 +274,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
}
// Folia start - region threading
@@ -2389,6 +2391,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2490,6 +2492,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.players;
}
@@ -298,7 +287,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
@Override
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
Optional<Holder<PoiType>> optional = PoiTypes.forState(oldState);
@@ -2826,6 +2834,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2963,6 +2971,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
@@ -310,7 +299,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
if (serverPlayer.isReceivingWaypoints()) {
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
}
@@ -2913,6 +2926,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -3044,6 +3057,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
@@ -323,10 +312,10 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
ServerLevel.this.updateSleepingPlayerList();
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 44f0e3a675c612e9ca2bc40cc3898bdbca0f6718..4b2dba8b30b72fb3acc00957b3e19d6fc178c99e 100644
index f0d45cb70af62b747c9235941f3fc45221b3b8e6..132645758827ee4d332909e701dde24e69699beb 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -219,7 +219,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -227,7 +227,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;
@@ -335,44 +324,25 @@ index 44f0e3a675c612e9ca2bc40cc3898bdbca0f6718..4b2dba8b30b72fb3acc00957b3e19d6f
private final PlayerAdvancements advancements;
private final ServerStatsCounter stats;
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
@@ -232,7 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private int lastSentFood = -99999999;
private boolean lastFoodSaturationZero = true;
public int lastSentExp = -99999999;
- private int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
+ public int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
public ParticleStatus particleStatus = ParticleStatus.ALL;
private boolean canChatColor = true;
@@ -241,7 +241,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private Entity camera;
@@ -248,7 +248,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private @Nullable Entity camera;
public boolean isChangingDimension;
public boolean seenCredits = false;
- private final ServerRecipeBook recipeBook;
+ protected ServerRecipeBook recipeBook; // Leaves - not final and private -> protected
@Nullable
private Vec3 levitationStartPos;
private @Nullable Vec3 levitationStartPos;
private int levitationStartTime;
@@ -436,6 +436,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
// Paper start - rewrite chunk system
private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
+ // Leaves start - player operation limiter
+ private int instaBreakCountPerTick = 0;
+ private int placeBlockCountPerTick = 0;
+ // Leaves end - player operation limiter
private boolean disconnected;
@@ -1495,7 +1495,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Luminol End - Cross Region Damage trace
@Override
public final boolean moonrise$isRealPlayer() {
@@ -924,6 +928,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// CraftBukkit end
this.tickClientLoadTimeout();
+ this.resetOperationCountPerTick(); // Leaves - player operation limiter
this.gameMode.tick();
this.wardenSpawnTracker.tick();
if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
@@ -2029,6 +2034,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
- private void tellNeutralMobsThatIDied() {
+ protected void tellNeutralMobsThatIDied() { // Leaves private -> protected
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
.getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS)
@@ -2132,6 +2132,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
this.teleportSpectators(teleportTransition, serverLevel);
@@ -384,82 +354,98 @@ index 44f0e3a675c612e9ca2bc40cc3898bdbca0f6718..4b2dba8b30b72fb3acc00957b3e19d6f
// CraftBukkit start
org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld());
this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
@@ -3577,4 +3587,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity();
}
// CraftBukkit end
+
+ // Leaves start - player operation limiter
+ protected void resetOperationCountPerTick() {
+ instaBreakCountPerTick = 0;
+ placeBlockCountPerTick = 0;
+ }
+
+ public int getInstaBreakCountPerTick() {
+ return instaBreakCountPerTick;
+ }
+
+ public int getPlaceBlockCountPerTick() {
+ return placeBlockCountPerTick;
+ }
+
+ public void addInstaBreakCountPerTick() {
+ ++instaBreakCountPerTick;
+ }
+
+ public void addPlaceBlockCountPerTick() {
+ ++placeBlockCountPerTick;
+ }
+
+ public boolean allowOperation() {
+ return (instaBreakCountPerTick == 0 || placeBlockCountPerTick == 0) && (instaBreakCountPerTick <= 1 && placeBlockCountPerTick <= 2);
+ }
+ // Leaves end - player operation limiter
}
diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java
index 144a2644c15f276f02bb3be859dc5d05a677ac55..c6a89e8936cffa49b3de153ed3c40e3cc9b8ae61 100644
--- a/net/minecraft/server/players/GameProfileCache.java
+++ b/net/minecraft/server/players/GameProfileCache.java
@@ -125,6 +125,12 @@ public class GameProfileCache {
// Paper end
diff --git a/net/minecraft/server/players/CachedUserNameToIdResolver.java b/net/minecraft/server/players/CachedUserNameToIdResolver.java
index 345bdb0ff82b8cd8c63e5ff1f2dabb68a1e54b77..c9a7c1c37155e0d339b880179a5988c9a6cb3797 100644
--- a/net/minecraft/server/players/CachedUserNameToIdResolver.java
+++ b/net/minecraft/server/players/CachedUserNameToIdResolver.java
@@ -122,6 +122,12 @@ public class CachedUserNameToIdResolver implements UserNameToIdResolver {
public Optional<GameProfile> get(String name) {
@Override
public Optional<NameAndId> get(String name) {
+ // Leaves start - fix bot
+ org.leavesmc.leaves.bot.ServerBot bot = org.leavesmc.leaves.bot.BotList.INSTANCE.getBotByName(name);
+ if (bot != null) {
+ return Optional.of(bot.getGameProfile());
+ return Optional.of(bot.nameAndId());
+ }
+ // Leaves end - fix bot
String string = name.toLowerCase(Locale.ROOT);
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
CachedUserNameToIdResolver.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
diff --git a/net/minecraft/server/players/NameAndId.java b/net/minecraft/server/players/NameAndId.java
index 05b4a75f6597e8613c91344d100bb7f005d169a7..9a5006362c12e972d031c48be4d30362d88d1c00 100644
--- a/net/minecraft/server/players/NameAndId.java
+++ b/net/minecraft/server/players/NameAndId.java
@@ -8,18 +8,22 @@ import java.util.UUID;
import net.minecraft.core.UUIDUtil;
import org.jspecify.annotations.Nullable;
-public record NameAndId(UUID id, String name) {
+public record NameAndId(UUID id, String name, boolean isBot) { // Leaves - fakeplayer
public static final Codec<NameAndId> CODEC = RecordCodecBuilder.create(
instance -> instance.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name))
.apply(instance, NameAndId::new)
);
public NameAndId(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(UUID uuid, String name) {
+ this(uuid, name, false); // Leaves - fakeplayer
}
public static @Nullable NameAndId fromJson(JsonObject json) {
@@ -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
} 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
}
// 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 cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74af2697442 100644
index 0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d..3a5319739f0687fc6f09b2ac8ee31716593fe0de 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -425,6 +425,19 @@ public abstract class PlayerList {
@@ -317,6 +317,19 @@ public abstract class PlayerList {
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false);
+ }
+ this.server.getBotList().bots.forEach(bot1 -> {
+ bot1.sendPlayerInfo(player);
+ bot1.sendFakeDataIfNeed(player, true);
+ }); // Leaves - render bot
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
+ }
+ // Leaves end - bot support
+ this.server.getBotList().bots.forEach(bot1 -> {
+ bot1.sendPlayerInfo(player);
+ bot1.sendFakeDataIfNeed(player, true);
+ }); // Leaves - render bot
+ }
+ // Leaves end - bot support
+
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -922,6 +935,12 @@ public abstract class PlayerList {
}
// Paper end - Add PlayerPostRespawnEvent
if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
@@ -791,6 +804,12 @@ public abstract class PlayerList {
).callEvent();
// Paper end
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
@@ -467,10 +453,10 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
+ }
+ // Leaves end - bot support
+
// CraftBukkit end
return serverPlayer;
@@ -1026,11 +1045,16 @@ public abstract class PlayerList {
}
@@ -892,11 +911,16 @@ public abstract class PlayerList {
public String[] getPlayerNamesArray() {
List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
@@ -478,20 +464,20 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
+ String[] strings = new String[this.players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
for (int i = 0; i < players.size(); i++) { // Folia - region threading
strings[i] = players.get(i).getGameProfile().getName(); // Folia - region threading
strings[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().getName();
+ strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().name();
+ }
+ // Leaves end - fakeplayer support
return strings;
}
@@ -1141,7 +1165,14 @@ public abstract class PlayerList {
@@ -1016,7 +1040,14 @@ public abstract class PlayerList {
}
@Nullable
public ServerPlayer getPlayerByName(String username) {
public @Nullable ServerPlayer getPlayerByName(String username) {
- return this.playersByName.get(username.toLowerCase(java.util.Locale.ROOT)); // Spigot
+ // Leaves start - fakeplayer support
+ username = username.toLowerCase(java.util.Locale.ROOT);
@@ -504,10 +490,10 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
}
public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey<Level> dimension, Packet<?> packet) {
@@ -1482,7 +1513,13 @@ public abstract class PlayerList {
@@ -1353,7 +1384,13 @@ public abstract class PlayerList {
}
@Nullable
public ServerPlayer getPlayer(UUID playerUUID) {
public @Nullable ServerPlayer getPlayer(UUID playerUUID) {
- return this.playersByUUID.get(playerUUID);
+ // Leaves start - fakeplayer support
+ ServerPlayer player = this.playersByUUID.get(playerUUID);
@@ -518,40 +504,12 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
+ // Leaves start - fakeplayer support
}
public boolean canBypassPlayerLimit(GameProfile profile) {
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd13444f4ad 100644
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
@@ -24,6 +24,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
public void trackWaypoint(WaypointTransmitter waypoint) {
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ // Leaves start - fakeplayer
+ if (waypoint instanceof org.leavesmc.leaves.bot.ServerBot bot && !bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.ENABLE_LOCATOR_BAR)) {
+ return;
+ }
+ // Leaves end - fakeplayer
this.waypoints.add(waypoint);
for (ServerPlayer serverPlayer : this.players) {
@@ -59,6 +64,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
// Folia - region threading
// Lophine start - unsafe waypoint bar
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
+ // Leaves start - fakeplayer
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ return;
+ }
+ // Leaves end - fakeplayer
this.players.add(player);
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
public @Nullable ServerPlayer getPlayer(String name) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a720d8db40ca56c997a4eeae14ebbc6fe764892c..118a21e7ba82832560fb0d8fb8d6b21beeb14000 100644
index 32299faedd89a848ca00288672ce85cad707dca0..3e44a61bd982dc822437f647a02a95affd988cdb 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1235,7 +1235,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
BlockPos onPosLegacy = this.getOnPosLegacy();
BlockState blockState = this.level().getBlockState(onPosLegacy);
@@ -560,7 +518,7 @@ index a720d8db40ca56c997a4eeae14ebbc6fe764892c..118a21e7ba82832560fb0d8fb8d6b21b
this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy);
}
@@ -1539,7 +1539,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1570,7 +1570,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
// Paper start - optimise collisions
@@ -570,10 +528,10 @@ index a720d8db40ca56c997a4eeae14ebbc6fe764892c..118a21e7ba82832560fb0d8fb8d6b21b
final boolean yZero = movement.y == 0.0;
final boolean zZero = movement.z == 0.0;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index f4f4f886b6558d39d292a45665953f497f84be53..12466e0294123a5922ee7694984d4d277a390ddd 100644
index 3fe9afe55b4d61db8030479d3d74b8656679cb10..c0ebd700caa950948c58846eaf164afc14f87f09 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3212,7 +3212,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -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);
@@ -582,16 +540,16 @@ index f4f4f886b6558d39d292a45665953f497f84be53..12466e0294123a5922ee7694984d4d27
this.setSpeed(this.getRiddenSpeed(player));
this.travel(riddenInput);
} else {
@@ -4062,7 +4062,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -4228,7 +4228,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
// Paper start - lag compensate eating
// we add 1 to the expected time to avoid lag compensating when we should not
final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L));
- if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !usingItem.useOnRelease()) {
+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide && !usingItem.useOnRelease()) { // Leaves - Fakeplayer skip this check
- 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()) {
this.useItemRemaining = 0;
// Paper end - lag compensate eating
this.completeUsingItem();
@@ -4239,6 +4239,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -4413,6 +4413,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
this.stopUsingItem();
}
@@ -613,13 +571,13 @@ index f4f4f886b6558d39d292a45665953f497f84be53..12466e0294123a5922ee7694984d4d27
+ // Leaves end - Fakeplayer
+
public void stopUsingItem() {
if (!this.level().isClientSide) {
if (!this.level().isClientSide()) {
boolean isUsingItem = this.isUsingItem();
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 6c933c27ce155eb516a9ede96fb2c3bd19251bfa..6e0784af90aab5c25100613f97d4492fa7d1b277 100644
index 83612969b6058f444fc17e360cdcc4a8846f79aa..29ca31b05ec5636243b13fee8b3399d5e21808b4 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -205,7 +205,7 @@ public abstract class Player extends LivingEntity {
@@ -168,7 +168,7 @@ public abstract class Player extends Avatar implements ContainerUser {
private int lastLevelUpTime;
public GameProfile gameProfile;
private boolean reducedDebugInfo;
@@ -627,8 +585,8 @@ index 6c933c27ce155eb516a9ede96fb2c3bd19251bfa..6e0784af90aab5c25100613f97d4492f
+ protected ItemStack lastItemInMainHand = ItemStack.EMPTY;
private final ItemCooldowns cooldowns = this.createItemCooldowns();
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
@Nullable
@@ -412,6 +412,12 @@ public abstract class Player extends LivingEntity {
public @Nullable FishingHook fishing;
@@ -349,6 +349,12 @@ public abstract class Player extends Avatar implements ContainerUser {
}
}
@@ -641,8 +599,8 @@ index 6c933c27ce155eb516a9ede96fb2c3bd19251bfa..6e0784af90aab5c25100613f97d4492f
@Override
protected float getMaxHeadRotationRelativeToBody() {
return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody();
@@ -714,7 +720,7 @@ public abstract class Player extends LivingEntity {
}
@@ -574,7 +580,7 @@ public abstract class Player extends Avatar implements ContainerUser {
public void removeEntitiesOnShoulder() {
}
- private void touch(Entity entity) {
@@ -650,17 +608,17 @@ index 6c933c27ce155eb516a9ede96fb2c3bd19251bfa..6e0784af90aab5c25100613f97d4492f
entity.playerTouch(this);
}
@@ -1339,7 +1345,7 @@ public abstract class Player extends LivingEntity {
this.sweepAttack();
}
@@ -1251,7 +1257,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
// CraftBukkit start - Add Velocity Event
boolean cancelled = false;
org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity();
- if (target instanceof ServerPlayer && target.hurtMarked) {
+ if ((target instanceof ServerPlayer && !(target instanceof org.leavesmc.leaves.bot.ServerBot)) && target.hurtMarked) { // Leaves - bot knockback
// CraftBukkit start - Add Velocity Event
boolean cancelled = false;
org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity();
diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java
index 7760ab1fe365b4bf1ab6c2ff953e8659a28008a8..76f6b0932633bc5670a1cdc76ff78b3bc725401d 100644
index 71f6acc07d222fe512bf8d9fbaad35cb36bcf2d6..a9f5d503fbe50e54f2f44be2ca6d414430f4481e 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 {
@@ -672,11 +630,11 @@ index 7760ab1fe365b4bf1ab6c2ff953e8659a28008a8..76f6b0932633bc5670a1cdc76ff78b3b
public int timeUntilLured;
public int timeUntilHooked;
public float fishAngle;
diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java
index 91ac54fb0ae9a06945476cbd1caa20be32c4a9fe..be380db0cb2f243b4a3cf8bd1b06d38debc5f6fd 100644
--- a/net/minecraft/world/entity/vehicle/AbstractBoat.java
+++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java
@@ -271,6 +271,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
diff --git a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
index fc1b3501114108d0166256c514a225337955e461..56bc87fefc82c77077bfed50accbde778c0059ea 100644
--- a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
+++ b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
@@ -270,6 +270,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
}
this.move(MoverType.SELF, this.getDeltaMovement());
@@ -688,7 +646,7 @@ index 91ac54fb0ae9a06945476cbd1caa20be32c4a9fe..be380db0cb2f243b4a3cf8bd1b06d38d
} else {
this.setDeltaMovement(Vec3.ZERO);
}
@@ -383,6 +388,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
@@ -380,6 +385,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
}
}
@@ -699,22 +657,22 @@ index 91ac54fb0ae9a06945476cbd1caa20be32c4a9fe..be380db0cb2f243b4a3cf8bd1b06d38d
+ }
+ // Leaves end - Fakeplayer
+
@Nullable
protected SoundEvent getPaddleSound() {
protected @Nullable SoundEvent getPaddleSound() {
return switch (this.getStatus()) {
case IN_WATER, UNDER_WATER, UNDER_FLOWING_WATER -> SoundEvents.BOAT_PADDLE_WATER;
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index bdc0ca1f625dc264bef6e5722ec66121ba48625a..525610be29d5077a3199287347b1b71cf9fd8abf 100644
index e7ea8849e8fa942709f505145e8076f064476206..4935234fba5977246aa303bf8162404813b5491e 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -407,6 +407,7 @@ public abstract class AbstractContainerMenu {
@@ -404,6 +404,7 @@ public abstract class AbstractContainerMenu {
private void doClick(int slotId, int button, ClickType clickType, Player player) {
private void doClick(int slotIndex, int button, ClickType clickType, Player player) {
Inventory inventory = player.getInventory();
+ if (!doClickCheck(slotId, button, clickType, player)) return; // Leaves - doClick check
+ if (!doClickCheck(slotIndex, button, clickType, player)) return; // Leaves - doClick check
if (clickType == ClickType.QUICK_CRAFT) {
int i = this.quickcraftStatus;
this.quickcraftStatus = getQuickcraftHeader(button);
@@ -685,6 +686,22 @@ public abstract class AbstractContainerMenu {
@@ -678,6 +679,22 @@ public abstract class AbstractContainerMenu {
}
}
@@ -738,10 +696,10 @@ index bdc0ca1f625dc264bef6e5722ec66121ba48625a..525610be29d5077a3199287347b1b71c
FeatureFlagSet featureFlagSet = player.level().enabledFeatures();
return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player)
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index a27e1d53abc2d8b8912226add33510067e10ed52..be0a267e5564a30c16f408cb311a448f354d60b4 100644
index 73a97f4f62fe7d27b441cab58c6c86ffce011060..ea6285b7f53f391c84519aa7ae39164cf5740b81 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -450,7 +450,7 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -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);
}
@@ -750,7 +708,7 @@ index a27e1d53abc2d8b8912226add33510067e10ed52..be0a267e5564a30c16f408cb311a448f
interactionResult = InteractionResult.FAIL; // cancel placement
// PAIL: Remove this when MC-99075 fixed
player.containerMenu.forceHeldSlot(hand);
@@ -946,6 +946,20 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
@@ -987,6 +987,20 @@ public final class ItemStack implements DataComponentHolder, ChangePublisher<net
}
}
@@ -772,7 +730,7 @@ index a27e1d53abc2d8b8912226add33510067e10ed52..be0a267e5564a30c16f408cb311a448f
return this.getItem().useOnRelease(this);
}
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index bff9574bece5f5581d9cc51a3f2b68b5c13c25c9..4bfe53c15c9b2effd24dddc48565efc9c102e56a 100644
index 557ea70254a8d6dd87c656098c5632bdcbe3df8f..1d60054146f970ec24054d2c76a27e2d8620ec67 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 {
@@ -785,7 +743,7 @@ index bff9574bece5f5581d9cc51a3f2b68b5c13c25c9..4bfe53c15c9b2effd24dddc48565efc9
double d1 = deltaMovement.x;
double d2 = deltaMovement.y;
diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java
index ecfd6a04ea1bac75bbb7e88554b73fc67e7f7358..2c9a55eecf44eaa62ef57597a94d657ad0b9cfc4 100644
index e9c40ecb2309d386a2214593181f2d4f289eb28b..17dff8aed5015bfd22d021e2fcf536265d179139 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 {
@@ -813,16 +771,3 @@ index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b5
this.id = id;
}
diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java
index fe44d8d17d2622b3d6021c11579af85ef96737bb..0aae211dc2048f8cd14213c2a868394d1ed16070 100644
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
@@ -19,7 +19,7 @@ import net.minecraft.util.datafix.DataFixTypes;
import net.minecraft.world.entity.player.Player;
import org.slf4j.Logger;
-public class PlayerDataStorage {
+public class PlayerDataStorage implements org.leavesmc.leaves.bot.IPlayerDataStorage {
private static final Logger LOGGER = LogUtils.getLogger();
private final File playerDir;
protected final DataFixer fixerUpper;
@@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 3 Oct 2025 19:43:36 +0800
Subject: [PATCH] Modify merge ItemEntity logic
Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius, when the merge radius is large and stacks containing many items get stuck in an unexpected position, individual items may never reach their destination. This configuration option is added to fix this behavior.
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index 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);
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 16:51:01 +0800
Subject: [PATCH] Leaves: Syncmatica Protocol
This patch is Powered by Syncmatica(https://github.com/End-Tech/syncmatica)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 1a749d9bee139975fa249839df93c3a1e48bf102..d81e22fe65cded98c201a7bbae8a51b22c6a20b4 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -338,9 +338,12 @@ public class ServerGamePacketListenerImpl
this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile);
this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat
this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event
+ this.exchangeTarget = new org.leavesmc.leaves.protocol.syncmatica.exchange.ExchangeTarget(this); // Leaves - Syncmatica Protocol
this.playerGameConnection = new io.papermc.paper.connection.PaperPlayerGameConnection(this); // Paper
}
+ public final org.leavesmc.leaves.protocol.syncmatica.exchange.ExchangeTarget exchangeTarget; // Leaves - Syncmatica Protocol
+
// Paper start - configuration phase API
@Override
public io.papermc.paper.connection.PlayerCommonConnection getApiConnection() {
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 13:03:42 +0800
Subject: [PATCH] Leaves: BBOR Protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 435acf0fe5e80ca371d1145befc2cfaa917a89e3..77577d0df9b14a7ad55b2866c2ac31863226458b 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
public void setLoaded(boolean loaded) {
this.loaded = loaded;
+ // Leaves start - bbor
+ if (loaded) {
+ org.leavesmc.leaves.protocol.BBORProtocol.onChunkLoaded(this);
+ }
+ // Leaves end - bbor
}
public Level getLevel() {
@@ -0,0 +1,140 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Fri, 13 Feb 2026 16:17:36 +0800
Subject: [PATCH] Leaves: Jade Protocol
This patch is Powered by Jade(https://github.com/Snownee/Jade)
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/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
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3835,7 +3835,7 @@ public class ServerGamePacketListenerImpl
}
@Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add PlayerLoadedWorldEvent
- private void markClientLoaded() {
+ public void markClientLoaded() { // Lophine - private -> public
// Paper start - Add PlayerLoadedWorldEvent
this.markClientLoaded(false);
}
diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java
index 901e4e9897e76cd4158d7f8bb8ec829df8ff8196..59b9373c7a14e42d9e5f691354a7616d16856215 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 {
public final AnimationState rollOutAnimationState = new AnimationState();
public final AnimationState rollUpAnimationState = new AnimationState();
public final AnimationState peekAnimationState = new AnimationState();
- private int scuteTime;
+ public int scuteTime; // Leaves - private -> public
private boolean peekReceivedClient = false;
public Armadillo(EntityType<? extends Animal> type, 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
--- 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 {
}
}
- private int getTicksLeftUntilAdult() {
+ public int getTicksLeftUntilAdult() { // Leaves - private -> public
return Math.max(0, ticksToBeFrog - this.age);
}
diff --git a/net/minecraft/world/level/storage/loot/LootPool.java b/net/minecraft/world/level/storage/loot/LootPool.java
index 43b8f4674602532f0273ebc5a0233476d10f6735..2ed995e68cf7812c74c3ba15b49450b2b5f3f0f8 100644
--- a/net/minecraft/world/level/storage/loot/LootPool.java
+++ b/net/minecraft/world/level/storage/loot/LootPool.java
@@ -37,7 +37,7 @@ public class LootPool {
)
.apply(instance, LootPool::new)
);
- private final List<LootPoolEntryContainer> entries;
+ public final List<LootPoolEntryContainer> entries; // Leaves - private -> public
private final List<LootItemCondition> conditions;
private final Predicate<LootContext> compositeCondition;
private final List<LootItemFunction> functions;
diff --git a/net/minecraft/world/level/storage/loot/LootTable.java b/net/minecraft/world/level/storage/loot/LootTable.java
index 35b5154473a3021dcae1f2ad016a77bcfb058c58..3d338b354c3d558a1c4ec20c149e8f26ed27da1e 100644
--- a/net/minecraft/world/level/storage/loot/LootTable.java
+++ b/net/minecraft/world/level/storage/loot/LootTable.java
@@ -50,7 +50,7 @@ public class LootTable {
public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of());
private final ContextKeySet paramSet;
private final Optional<Identifier> randomSequence;
- private final List<LootPool> pools;
+ public final List<LootPool> pools; // Leaves - private -> public
private final List<LootItemFunction> functions;
private final BiFunction<ItemStack, LootContext, ItemStack> compositeFunction;
public org.bukkit.craftbukkit.CraftLootTable craftLootTable; // CraftBukkit
diff --git a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
index eeaa49e9f70a18b5d39493aeff73f31b05ac2faa..8cd0403d7873c4c37caef75935b06b056c3d951d 100644
--- a/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
+++ b/net/minecraft/world/level/storage/loot/entries/CompositeEntryBase.java
@@ -16,7 +16,7 @@ public abstract class CompositeEntryBase extends LootPoolEntryContainer {
return "Empty children list";
}
};
- protected final List<LootPoolEntryContainer> children;
+ public final List<LootPoolEntryContainer> children; // Leaves - private -> public
private final ComposableEntryContainer composedChildren;
protected CompositeEntryBase(List<LootPoolEntryContainer> children, List<LootItemCondition> conditions) {
diff --git a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
index cfa05e882d2987cfab4c9d555a2de065b29fdf7e..4bacc9e2fb94d1b24887e7f0e9ce628814393209 100644
--- a/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
+++ b/net/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer.java
@@ -14,7 +14,7 @@ import net.minecraft.world.level.storage.loot.predicates.ConditionUserBuilder;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
public abstract class LootPoolEntryContainer implements ComposableEntryContainer {
- protected final List<LootItemCondition> conditions;
+ public final List<LootItemCondition> conditions; // Leaves - private -> public
private final Predicate<LootContext> compositeCondition;
protected LootPoolEntryContainer(List<LootItemCondition> conditions) {
diff --git a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
index 141026601cd9a4561426b85fd1f8e7dc0544fbd7..a5d7ebb93c147bf0f806ac3c9b2dc4b878573944 100644
--- a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
+++ b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java
@@ -29,7 +29,7 @@ public class NestedLootTable extends LootPoolSingletonContainer {
return "->{inline}";
}
};
- private final Either<ResourceKey<LootTable>, LootTable> contents;
+ public final Either<ResourceKey<LootTable>, LootTable> contents; // Leaves - private -> public
private NestedLootTable(
Either<ResourceKey<LootTable>, LootTable> contents, int weight, int quality, List<LootItemCondition> conditions, List<LootItemFunction> functions
diff --git a/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java b/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
index bae72197acc929c7ed3e964f156115d728eb2176..8f3094f42f3366a1313d70c0b27fbe5632b2082a 100644
--- a/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
+++ b/net/minecraft/world/level/storage/loot/predicates/CompositeLootItemCondition.java
@@ -12,7 +12,7 @@ import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.ValidationContext;
public abstract class CompositeLootItemCondition implements LootItemCondition {
- protected final List<LootItemCondition> terms;
+ public final List<LootItemCondition> terms; // Leaves - private -> public
private final Predicate<LootContext> composedPredicate;
protected CompositeLootItemCondition(List<LootItemCondition> terms, Predicate<LootContext> composedPredicate) {
@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Fri, 7 Feb 2025 14:23:43 +0800
Subject: [PATCH] Leaves: Xaero Map Protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 3a5319739f0687fc6f09b2ac8ee31716593fe0de..36cd1a0307ff1a734eb5f4f3cc013781692e7ad8 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1126,6 +1126,7 @@ public abstract class PlayerList {
//player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level))); // Paper - rewrite chunk system
//player.connection.send(new ClientboundSetSimulationDistancePacket(io.papermc.paper.FeatureHooks.getSimulationDistance(level))); // Paper - rewrite chunk system
// Paper end - view distances
+ org.leavesmc.leaves.protocol.XaeroMapProtocol.onSendWorldInfo(player); // Leaves - xaero map protocol
if (level.isRaining()) {
// CraftBukkit start - handle player weather
// player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F));
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Thu, 27 Mar 2025 13:04:35 +0800
Subject: [PATCH] Leaves: Support REI protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
index d02609198253b51f632db46c40afd737d686c520..7296e0b73f1c8e32374f39238d1dfac62bc41afb 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 {
);
}
+ // Leaves start - REI
+ public SlotDisplay getResult() {
+ return this.result.display();
+ }
+ // Leaves end - REI
+
// CraftBukkit start
@Override
public org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id) {
diff --git a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java
index 6582370cfa3d58a7ac08d574e26e7a93d243bdaa..07501a27e6032e578b823d9b617166a9e78fcb20 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 {
return Optional.of(this.addition);
}
+ // Leaves start
+ public Holder<TrimPattern> pattern() {
+ return pattern;
+ }
+ // Leaves end
+
@Override
public RecipeSerializer<SmithingTrimRecipe> getSerializer() {
return RecipeSerializer.SMITHING_TRIM;
@@ -0,0 +1,95 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 27 Oct 2025 15:38:29 +0800
Subject: [PATCH] Leaves: Wool Hopper Counter
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: MIT
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 6a51bace3151646afae9de820d9c8977a0221df4..474ca0ce0d3095fc586f8f9e9a584ed4f7c91471 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
}
+ // Leaves start - Wool hopper counter
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockEntity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
+ if (woolColor != null) {
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ flag |= suckInItems(level, blockEntity);
+ if (!flag) {
+ break;
+ } else {
+ woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos));
+ }
+ }
+ }
+ }
+ // Leaves end - Wool hopper counter
+
if (flag) {
blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
+ // Leaves start - Wool hopper counter
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
+ blockEntity.setCooldown(0);
+ return true;
+ }
+ // Leaves end - Wool hopper counter
setChanged(level, pos, state);
// Leaves start - Lithium Sleeping Block Entity
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
@@ -462,6 +484,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
// Paper end - Perf: Optimize Hoppers
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
+ // Leaves start - hopper counter
+ if (org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
+ if (woolHopperCounter(level, pos, level.getBlockState(pos), HopperBlockEntity.getContainerAt(level, pos))) {
+ return true;
+ }
+ }
+ // Leaves end - hopper counter
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
if (attachedContainer == null) {
return false;
@@ -537,6 +566,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
}
+ // Leaves start - hopper counter
+ private static boolean woolHopperCounter(Level level, BlockPos blockPos, BlockState state, @Nullable Container container) {
+ if (container == null) {
+ return false;
+ }
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockPos.relative(state.getValue(HopperBlock.FACING)));
+ if (woolColor != null) {
+ for (int i = 0; i < container.getContainerSize(); ++i) {
+ if (!container.getItem(i).isEmpty()) {
+ ItemStack itemstack = container.getItem(i);
+ org.leavesmc.leaves.util.HopperCounter.getCounter(woolColor).add(level.getServer(), itemstack);
+ container.setItem(i, ItemStack.EMPTY);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ // Leaves end - hopper counter
+
private static int[] getSlots(Container container, Direction direction) {
if (container instanceof WorldlyContainer worldlyContainer) {
return worldlyContainer.getSlotsForFace(direction);
@@ -681,6 +730,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
public static boolean addItem(Container container, ItemEntity item) {
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && item.isRemoved()) return false; // Leaves - Wool hopper counter
boolean flag = false;
// CraftBukkit start
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
@@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Mon, 3 Feb 2025 13:51:26 +0800
Subject: [PATCH] Leaves: Alternative block placement Protocol
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: MIT
This patch is Powered by
carpet-extra(https://github.com/gnembon/carpet-extra)
MasaGadget(https://github.com/plusls/MasaGadget)
litematica(https://github.com/maruohon/litematica)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 43e9fd5684d15f8643524132e60266071c6dc454..62db0ba9c824959f953d452ab7aafcde01b10bcd 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();
this.player.resetLastActionTime();
int maxY = this.player.level().getMaxY();
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 73ce7c82c0bd28c2e43ca40ba35c4603b21375ad..a5d3caab2072b2c9bf8fdcbdb7c52c2dee16cfaf 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -147,7 +147,7 @@ public class BlockItem extends Item {
}
protected @Nullable BlockState getPlacementState(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
--- 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;
LevelReader level = context.getLevel();
BlockPos clickedPos = 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;
break;
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
index 492b1615d96133c5082e0f16015f114299f8082f..fb47a2acb0e4232359f5da061c1620a7b1d6c476 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) {
}
+ // Leaves start - alternativeBlockPlacement
+ public @Nullable BlockState getRealStateForPlacement(BlockPlaceContext context) {
+ BlockState vanillaState = this.getStateForPlacement(context);
+ switch (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.alternativeBlockPlacement) {
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET -> {
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacement(this, context);
+ if (tryState != null) {
+ return tryState;
+ }
+ }
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET_FIX -> {
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacementFix(this, context);
+ if (tryState != null) {
+ return tryState;
+ }
+ }
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.LITEMATICA -> {
+ if (vanillaState != null) {
+ return org.leavesmc.leaves.protocol.LitematicaEasyPlaceProtocol.applyPlacementProtocol(vanillaState, context);
+ }
+ }
+ }
+ return vanillaState;
+ }
+ // Leaves end - alternativeBlockPlacement
+
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState();
}
@@ -0,0 +1,567 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 16 Nov 2025 15:48:12 +0800
Subject: [PATCH] Leaves: Replay Mod API
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves) & ReplayMod (https://github.com/ReplayMod)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
This patch is Powered by ReplayMod (https://github.com/ReplayMod)
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
index f046aca874eb3376696baaad3719a6987afbfe22..268b2c6b981c8164fb829eb8a33beb213fe60bcf 100644
--- a/net/minecraft/commands/CommandSourceStack.java
+++ b/net/minecraft/commands/CommandSourceStack.java
@@ -562,7 +562,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
@Override
public Collection<String> getOnlinePlayerNames() {
- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player
}
@Override
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
index af71e0e1eb1c93745f3e4954ecc8fbd2ad4808a3..f3829564681faff3ae8971ed90b947b4a082a636 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);
} 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);
} else if (this.entityUUID != null) {
for (ServerLevel serverLevel : source.getServer().getAllLevels()) {
Entity entity = serverLevel.getEntity(this.entityUUID);
- if (entity != null) {
+ if (entity != null && !(entity instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
if (entity.getType().isEnabled(source.enabledFeatures())) {
return List.of(entity);
}
@@ -144,7 +145,7 @@ public class EntitySelector {
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
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
} 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);
}
}
+ list.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
return this.sortAndLimit(vec3, list);
}
@@ -190,9 +192,11 @@ public class EntitySelector {
this.checkPermissions(source);
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);
} 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);
} else {
Vec3 vec3 = this.position.apply(source.getPosition());
@@ -204,11 +208,11 @@ public class EntitySelector {
int resultLimit = this.getResultLimit();
List<ServerPlayer> players;
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
} else {
players = 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) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index dfcf8eb7dc422a55d94d6eb9eb1451c7c14a1d56..9130f1fbf15500f2149418b73ae2a374bba22eee 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1896,7 +1896,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
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
@Override
public int getPlayerCount() {
- return this.playerList.getPlayerCount();
+ return this.playerList.realPlayers.size(); // Leaves - only real player
}
public String[] getPlayerNames() {
@@ -2309,7 +2309,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} else {
int i = 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
// 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
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
}
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
index 5bf7eb5b906cefa57a1dfcf828ff7872dbceac4f..85923708c32a0597e98e028eeec501f2ea07b63b 100644
--- a/net/minecraft/server/PlayerAdvancements.java
+++ b/net/minecraft/server/PlayerAdvancements.java
@@ -167,7 +167,7 @@ public class PlayerAdvancements {
public boolean award(AdvancementHolder advancement, String criterionKey) {
// Leaves start - bot can't get advancement
- if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot || player instanceof org.leavesmc.leaves.replay.ServerPhotographer) { // Leaves - and photographer
return false;
}
// Leaves end - bot can't get advancement
diff --git a/net/minecraft/server/ServerScoreboard.java b/net/minecraft/server/ServerScoreboard.java
index 04a62e5ab9c0d0b9b7959280b0e0ea3ff388c017..e4260ec1938a43d41e007ad67a2b5be96a00227c 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);
- 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 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);
diff --git a/net/minecraft/server/commands/ListPlayersCommand.java b/net/minecraft/server/commands/ListPlayersCommand.java
index e7c778a7f292fd0749cbd5e6586ad1b93ac7f29e..024b56405bb58801b17a6adad7fec7a461d12a5c 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) {
PlayerList playerList = source.getServer().getPlayerList();
// CraftBukkit start
- List<ServerPlayer> playersTemp = playerList.getPlayers();
+ List<ServerPlayer> playersTemp = playerList.realPlayers;
if (source.getBukkitSender() instanceof org.bukkit.entity.Player) {
org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender();
playersTemp = playersTemp.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList());
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
index 590891d70a71ab30ceae3a3cf1923745e7c20b26..0ede1e5c73a0071e854de70f81ae1fc6a1d6dc59 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();
return SharedSuggestionProvider.suggest(
- playerList.getPlayers()
+ playerList.realPlayers // Leaves - only real player
.stream()
.filter(serverPlayer -> !playerList.isOp(serverPlayer.nameAndId()))
.map(serverPlayer -> serverPlayer.getGameProfile().name()),
diff --git a/net/minecraft/server/commands/ParticleCommand.java b/net/minecraft/server/commands/ParticleCommand.java
index b5cb0fd45c1e33f40ff38e86772c9e6cc06c10a0..e9ac6ee47fd9c3d73e55a3467bb1c53f931609d0 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
)
)
.then(
@@ -50,7 +50,7 @@ public class ParticleCommand {
0.0F,
0,
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -68,7 +68,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -82,7 +82,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
true,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
)
)
.then(
@@ -112,7 +112,7 @@ public class ParticleCommand {
FloatArgumentType.getFloat(context1, "speed"),
IntegerArgumentType.getInteger(context1, "count"),
false,
- context1.getSource().getServer().getPlayerList().getPlayers()
+ context1.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
--- 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()
.getPlayerList()
- .getPlayers()
+ .realPlayers // Leaves - only real players
.stream()
.filter(player -> player == entityOrException || player.getTeam() == team)
.toList();
diff --git a/net/minecraft/server/commands/WhitelistCommand.java b/net/minecraft/server/commands/WhitelistCommand.java
index 305273583b3d2ad233c6cd67883baad15fe572eb..ce2939eac9c66e0c6eaac1570c4da19d908662ad 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();
return SharedSuggestionProvider.suggest(
- playerList.getPlayers()
+ playerList.realPlayers // Leaves - only real player
.stream()
.map(Player::nameAndId)
.filter(nameAndId -> !playerList.getWhiteList().isWhiteListed(nameAndId))
diff --git a/net/minecraft/server/gui/PlayerListComponent.java b/net/minecraft/server/gui/PlayerListComponent.java
index 5a8cd3e6b448a4472092690cf589bca10b142126..158593b1a6384db635a1f224919b24c174944b10 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<>();
- 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());
}
this.setListData(list);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 14516c3ebd092e6f230804145a60dc851f34230b..bd33a381490ec3f03af9d22c9337f5d686014d85 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);
// 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);
}
// 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);
// 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);
}
// 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
--- 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
// CraftBukkit start
private org.bukkit.craftbukkit.CraftServer cserver;
@@ -218,6 +219,123 @@ public abstract class PlayerList {
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
+ // Leaves start - replay mod api
+ public void placeNewPhotographer(Connection connection, org.leavesmc.leaves.replay.ServerPhotographer player, ServerLevel worldserver) {
+ player.isRealPlayer = true; // Paper
+ player.loginTime = System.currentTimeMillis(); // Paper
+
+ ServerLevel worldserver1 = worldserver;
+
+ player.setServerLevel(worldserver1);
+ player.spawnIn(worldserver1);
+ player.gameMode.setLevel((ServerLevel) 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
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
+ RecipeManager craftingmanager = this.server.getRecipeManager();
+ playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes()));
+
+ this.sendPlayerPermissionLevel(player);
+ player.getStats().markAllDirty();
+ player.getRecipeBook().sendInitialRecipeBook(player);
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
+ this.server.invalidateStatus();
+
+ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
+ ServerStatus serverping = this.server.getStatus();
+
+ if (serverping != null) {
+ player.sendServerStatus(serverping);
+ }
+
+ this.players.add(player);
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
+ this.playersByUUID.put(player.getUUID(), player);
+
+ player.suppressTrackerForLogin = true;
+ worldserver1.getCurrentWorldData().connections.add(player.connection.connection);
+ worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
+
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
+ if (!player.connection.isAcceptingMessages()) {
+ return;
+ }
+
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
+
+ // Leaves start - bot support
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
+ if (bot != null) {
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false);
+ }
+ this.server.getBotList().bots.forEach(bot1 -> {
+ bot1.sendPlayerInfo(player);
+ bot1.sendFakeDataIfNeed(player, true);
+ }); // Leaves - render bot
+ }
+ // Leaves end - bot support
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
+ final List<ServerPlayer> playerList = List.copyOf(this.players); // Lophine - copy to avoid ConcurrentModificationException
+ for (ServerPlayer serverPlayer : playerList) {
+ if (serverPlayer == player || !bukkitPlayer.canSee(serverPlayer.getBukkitEntity())) {
+ continue;
+ }
+
+ // Leaves start - skip photographer
+ if (serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
+ continue;
+ }
+ // Leaves end - skip photographer
+
+ onlinePlayers.add(serverPlayer);
+ }
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
+ }
+
+ player.sentListPacket = true;
+ player.suppressTrackerForLogin = false;
+ player.level().getChunkSource().chunkMap.addEntity(player);
+
+ this.sendLevelInfo(player, worldserver1);
+
+ if (player.level() == worldserver1 && !worldserver1.players().contains(player)) {
+ worldserver1.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ }
+
+ worldserver1 = player.level();
+ for (MobEffectInstance mobeffect : player.getActiveEffects()) {
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect, false));
+ }
+
+ if (player.isDeadOrDying()) {
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
+ worldserver1.getLightEngine(), null, null, false)
+ );
+ }
+ }
+ // Leaves end - replay mod api
+
public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) {
player.isRealPlayer = true; // Paper
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
@@ -292,6 +410,7 @@ public abstract class PlayerList {
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
+ this.realPlayers.add(player); // Leaves - replay api
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
@@ -507,6 +626,7 @@ public abstract class PlayerList {
}
protected void save(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 {
}
}
+ // Leaves start - replay mod api
+ public void removePhotographer(org.leavesmc.leaves.replay.ServerPhotographer entityplayer) {
+ ServerLevel worldserver = entityplayer.level();
+
+ entityplayer.awardStat(Stats.LEAVE_GAME);
+
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT);
+ }
+
+ if (server.isSameThread()) entityplayer.doTick();
+
+ if (this.collideRuleTeamName != null) {
+ final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
+ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
+ if (entityplayer.getTeam() == team && team != null) {
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
+ }
+ }
+
+ worldserver.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));
+ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer);
+ UUID uuid = entityplayer.getUUID();
+ ServerPlayer entityplayer1 = this.playersByUUID.get(uuid);
+
+ if (entityplayer1 == entityplayer) {
+ this.playersByUUID.remove(uuid);
+ }
+
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
+ }
+ // Leaves stop - replay mod api
+
public net.kyori.adventure.text.@Nullable Component remove(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 {
player.getBukkitEntity().packetProcessor.close(); // Folia - region threading
player.getAdvancements().stopListening();
this.players.remove(player);
+ this.realPlayers.remove(player); // Leaves - replay api
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
this.server.getCustomBossEvents().onPlayerDisconnect(player);
UUID uuid = player.getUUID();
@@ -910,15 +1069,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
for (int i = 0; i < players.size(); i++) { // Folia - region threading
strings[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 = 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
}
// Leaves end - fakeplayer support
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index c0ebd700caa950948c58846eaf164afc14f87f09..e4ae4354e81f34f0db410333fc9b8e17383a5f41 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
public int useItemRemaining;
protected int fallFlyTicks;
private long lastKineticHitFeedbackTime = -2147483648L;
- private BlockPos lastPos;
+ protected BlockPos lastPos;
private Optional<BlockPos> lastClimbablePos = Optional.empty();
private @Nullable DamageSource lastDamageSource;
private long lastDamageStamp = Long.MIN_VALUE; // Folia - region threading
@@ -0,0 +1,243 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 7 Feb 2026 23:57:50 +0800
Subject: [PATCH] Leaves: Catch update suppression crash
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/network/PacketProcessor.java b/net/minecraft/network/PacketProcessor.java
index cf162ec136309d05c5aa03042652ab3932935917..469ffd54eb5af980f49061bbec0a72f4e888f8a3 100644
--- a/net/minecraft/network/PacketProcessor.java
+++ b/net/minecraft/network/PacketProcessor.java
@@ -107,7 +107,20 @@ public class PacketProcessor implements AutoCloseable {
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(ListenerAndPacket.this.packet.getClass().getName()))); try { // Folia - profiler
this.packet.handle(this.listener);
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
- } catch (Exception var3) {
+ // Leaves start - update suppression crash fix
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ } catch (Exception var3) {
+ if (var3.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ }
+ // Leaves end - update suppression crash fix
if (var3 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) {
throw PacketUtils.makeReportedException(var3, this.packet, this.listener);
}
diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java
index ab80a66646a7ebe2862221ac342b06c14fcfc734..7834f3da4d0ff4a5cdec46b023d7348369a12e96 100644
--- a/net/minecraft/network/protocol/PacketUtils.java
+++ b/net/minecraft/network/protocol/PacketUtils.java
@@ -34,6 +34,7 @@ public class PacketUtils {
}
public static <T extends PacketListener> ReportedException makeReportedException(Exception exception, Packet<T> packet, T packetListener) {
+
if (exception instanceof ReportedException reportedException) {
fillCrashReport(reportedException.getReport(), packetListener, packet);
return reportedException;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 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,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 15 Nov 2025 01:12:39 +0800
Subject: [PATCH] Leaves: CCE update suppression
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 46d6c6e3befc70a6878e12a4d75575e6d48d10ca..77840814806c7d07b58cd716cf7ec095e894498a 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -183,7 +183,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
protected int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos, Direction direction) {
// Leaves start - update suppression crash fix
try {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce ?
+ AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container) level.getBlockEntity(pos)) : // Leaves - make cce happy(?)
+ AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
} catch (ClassCastException ex) {
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
@@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Wed, 14 Jun 2023 12:07:07 +0800
Subject: [PATCH] Leaves: Redstone ignore upwards update
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
index 578e7c8dc601f53cf2a068685c6901bfaf47e763..0686aa5425c00e10beb381f3c3ff3c554603cd49 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -58,6 +58,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
BlockState neighborState,
RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)
? Blocks.AIR.defaultBlockState()
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index ba253a9af6141d8ea99c064e3cc0c6486c221098..48f9e234e4025633cbc41d334d88ada36c2e0d7b 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -178,7 +178,7 @@ public class RedStoneWireBlock extends Block {
RandomSource random
) {
if (direction == Direction.DOWN) {
- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state;
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19
} else if (direction == Direction.UP) {
return this.getConnectionState(level, state, pos);
} else {
@@ -238,7 +238,7 @@ public class RedStoneWireBlock extends Block {
BlockPos blockPos = pos.relative(direction);
BlockState blockState = level.getBlockState(blockPos);
if (nonNormalCubeAbove) {
- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState);
+ boolean flag = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19
if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) {
if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) {
return RedstoneSide.UP;
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
index 87e1a32376adc5a15f035b62bc1f672c507cd230..26c10c1fecb976f3ef0338aa78603d454d1b3fe8 100644
--- a/net/minecraft/world/level/block/RepeaterBlock.java
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
@@ -68,6 +68,7 @@ public class RepeaterBlock extends DiodeBlock {
BlockState neighborState,
RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
if (direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)) {
return Blocks.AIR.defaultBlockState();
} else {
@@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 17 Nov 2025 18:41:08 +0800
Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index c7f578c117baccb10c0c15b05a6c04e073f15da8..aee3f98173de1b2c5a5278919a5d21b4bca03b7b 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -472,7 +472,7 @@ public final class RegionizedWorldData {
public long lastMidTickExecuteFailure;
// From Level
public boolean populating;
- public final CollectingNeighborUpdater neighborUpdater;
+ public final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater;
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public final Map<BlockPos, CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
@@ -531,7 +531,7 @@ public final class RegionizedWorldData {
this.world = world;
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
- this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world) : new CollectingNeighborUpdater(world, world.neighbourUpdateMax); // Lophine - Instant Block Updater
this.nearbyPlayers = new NearbyPlayers(world);
this.wireHandler = new alternate.current.wire.WireHandler(world);
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 284bd9703b11804f51273ecfaa5cd44925726f5f..9756caff0b7403c212987e58c08a2da09bdeb962 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -927,12 +927,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper - rewrite chunk system
profilerFiller.pop();
profilerFiller.push("debugSynchronizers");
+ // Lophine start - instant neighbor updates
+ if (regionizedWorldData.neighborUpdater instanceof net.minecraft.world.level.redstone.CollectingNeighborUpdater neighborUpdater) {
if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) {
- regionizedWorldData.neighborUpdater // Folia - region threading
- .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
+ neighborUpdater // Folia - region threading
+ .setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos));
} else {
- regionizedWorldData.neighborUpdater.setDebugListener(null); // Folia - region threading
+ neighborUpdater.setDebugListener(null); // Folia - region threading
}
+ }
+ // Lophine end - instant neighbor updates
this.debugSynchronizers.tick(this.server.debugSubscribers());
profilerFiller.pop();
@@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:24:32 +0800
Subject: [PATCH] Revert TrapDoorBlock changes form Paper
diff --git a/net/minecraft/world/level/block/TrapDoorBlock.java b/net/minecraft/world/level/block/TrapDoorBlock.java
index b45ae50db32c4156b8f8008335673d20c570c72d..af78831441f362b0129aa864854ce5a64d544640 100644
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -128,37 +128,7 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
if (!level.isClientSide()) {
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
if (hasNeighborSignal != state.getValue(POWERED)) {
- // CraftBukkit start
- org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
- int power = bblock.getBlockPower();
- int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
-
- if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
- org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
- level.getCraftServer().getPluginManager().callEvent(eventRedstone);
- hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
- }
- // CraftBukkit end
- // Paper start - break redstone on trapdoors early
- boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
- // note: this must run before any state for this block/its neighbours are written to the world
- // we allow the redstone event to fire so that plugins can block
- if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
- // in this case, first check for the redstone on top first
- BlockPos abovePos = pos.above();
- BlockState above = level.getBlockState(abovePos);
- if (above.getBlock() instanceof RedStoneWireBlock) {
- level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
- Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
- // now check that this didn't change our state
- if (level.getBlockState(pos) != state) {
- // our state was changed, so we cannot propagate this update
- return;
- }
- }
- }
- if (open) {
- // Paper end - break redstone on trapdoors early
+ if (state.getValue(OPEN) != hasNeighborSignal) {
state = state.setValue(OPEN, hasNeighborSignal);
this.playSound(null, level, pos, hasNeighborSignal);
}
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:35:13 +0800
Subject: [PATCH] Leaves: Prevent loss of item drops due to update suppression
when breaking blocks
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index 3301e521a79adbc6dd76be05e69cce1c97f8697e..8dc1db0e6bafba19e07a7fa78f3920d572d38466 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -386,7 +386,18 @@ public class ServerPlayerGameMode {
this.level.getCurrentWorldData().captureDrops = new java.util.ArrayList<>(); // Folia - region threading
// CraftBukkit end
BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player);
- boolean flag = this.level.removeBlock(pos, false);
+ // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks
+ boolean flag;
+ org.leavesmc.leaves.util.UpdateSuppressionException ex = null;
+ try {
+ flag = this.level.removeBlock(pos, false);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) {
+ ex = e;
+ ex.provideBlock(level, pos, block);
+ ex.providePlayer(this.player);
+ flag = false;
+ }
+ // Leaves end - Prevent loss of item drops due to update suppression when breaking blocks
if (SharedConstants.DEBUG_BLOCK_BREAK) {
LOGGER.info("server broke {} {} -> {}", pos, blockState1, this.level.getBlockState(pos));
}
@@ -418,6 +429,7 @@ public class ServerPlayerGameMode {
if (event.isDropItems()) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
}
+ if (ex != null) throw ex; // Leaves - Prevent loss of item drops due to update suppression when breaking blocks
// Drop event experience
if (flag) {
@@ -0,0 +1,811 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 23:11:26 +0800
Subject: [PATCH] Leaves: Old Block remove behaviour
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java
index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644
--- a/net/minecraft/world/Containers.java
+++ b/net/minecraft/world/Containers.java
@@ -51,4 +51,15 @@ public class Containers {
public static void updateNeighboursAfterDestroy(BlockState state, Level level, BlockPos pos) {
level.updateNeighbourForOutputSignal(pos, state.getBlock());
}
+
+ // Leaves start - behaviour 1.21.1-
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof Container container) {
+ dropContents(level, pos, container);
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
}
diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
index dcc1bb4fcee9646212a424c03f77370ffa577fee..ca5cf7526082b9d3a7887dd77313e2c0012efebb 100644
--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java
+++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
@@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof AbstractFurnaceBlockEntity) {
+ if (level instanceof ServerLevel) {
+ Containers.dropContents(level, pos, (AbstractFurnaceBlockEntity)blockEntity);
+ ((AbstractFurnaceBlockEntity)blockEntity).getRecipesToAwardAndPopExperience((ServerLevel)level, net.minecraft.world.phys.Vec3.atCenterOf(pos));
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ level.updateNeighbourForOutputSignal(pos, this);
+ } else {
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
index 8139799a24274cfb70a99d301c2688c0360720c6..b224d3756120cd82d1381c55a95ad63c18c123b7 100644
--- a/net/minecraft/world/level/block/BarrelBlock.java
+++ b/net/minecraft/world/level/block/BarrelBlock.java
@@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock {
return InteractionResult.SUCCESS;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
index 7135a6bc87f90fafa94d0783aaf7b42d66449010..afd06de092a75c6c4f7b8848055e314b0c241029 100644
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
@@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (this.getSignalForState(state) > 0) {
+ this.updateNeighbours(level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && this.getSignalForState(state) > 0) {
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
index 504f38ce16f6a5d2b748a5c71c69f5be5886ceb5..db0b38db5675cb248e31e7a5988c35496561ad6f 100644
--- a/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
@@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ if (state.getValue(this.getShapeProperty()).isSlope()) {
+ level.updateNeighborsAt(pos.above(), this);
+ }
+
+ if (this.isStraight) {
+ level.updateNeighborsAt(pos, this);
+ level.updateNeighborsAt(pos.below(), this);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
index bd6dc109fd9c37666f23ccd17c0eab8aff95e777..e25103c62a41e3fb0a8f7e84496cacc73ed71a74 100644
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock {
level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
index 27ca29f1d3e0e68229edef3b32634ce9b054824a..ea2c5d79fc41f58b263ec34b53df436e0043ef53 100644
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff();
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
index b9e11a361e91cf3d5c929330fc0ba59cfe903198..4985fcfef75abbe2be9cd5e6111de4d60237bafa 100644
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof CampfireBlockEntity) {
+ net.minecraft.world.Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems());
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier, boolean pastEdges) {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
index fa2dce759419f62825000718361f47c6f208cdb2..64c0616c294bd7c7b62ae376d50369500b948390 100644
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -280,6 +280,14 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
return this.chestCanConnectTo(blockState) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
index cea0f015290137a5284f4a3021c954272b3db543..53d983505b4c92824083ecd123901874d04704c5 100644
--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
@@ -149,6 +149,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof ChiseledBookShelfBlockEntity chiseledBookShelfBlockEntity && !chiseledBookShelfBlockEntity.isEmpty()) {
+ for (int i = 0; i < 6; i++) {
+ ItemStack item = chiseledBookShelfBlockEntity.getItem(i);
+ if (!item.isEmpty()) {
+ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), item);
+ }
+ }
+
+ chiseledBookShelfBlockEntity.clearContent();
+ level.updateNeighbourForOutputSignal(pos, this);
+ }
+
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
index 3faa541c4a4623e915269d6241e1a3a3c6e374ff..18c660893a33ecf70c3d225525505852e4449182 100644
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -128,6 +128,14 @@ public class CrafterBlock extends BaseEntityBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
index dfb9a10622ba2a0c2759bb563fefd729f1109865..c735e7de1b88de531dd00a2cc2dd4a1394b808e6 100644
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
builder.add(AXIS, STATE, NATURAL);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (level.getBlockEntity(pos) instanceof CreakingHeartBlockEntity creakingHeartBlockEntity) {
+ creakingHeartBlockEntity.removeProtector(null);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
index dd20e3c57352859ab931692445c83669da94f629..e8c216831b66cd0f4e989797030119388a3378a5 100644
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -164,6 +164,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
return new DecoratedPotBlockEntity(pos, state);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
index b34e051b4a672d44872a74e810f978373e73af05..4525d718016fe125e3cdb1c1798fe9483213ba49 100644
--- a/net/minecraft/world/level/block/DiodeBlock.java
+++ b/net/minecraft/world/level/block/DiodeBlock.java
@@ -176,6 +176,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ this.updateNeighborsInFront(level, pos, state);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
index 2ef2861041f3aaf85ea64458c43c5d83fdab9bfc..0828d663647f7c3267a4a9392a3b0b8e6e54928c 100644
--- a/net/minecraft/world/level/block/DispenserBlock.java
+++ b/net/minecraft/world/level/block/DispenserBlock.java
@@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
index 3c349b4216d934068c26017820884593662f471e..4c5a12784e97e599891d40d5ce784b4f8c1e5b15 100644
--- a/net/minecraft/world/level/block/HopperBlock.java
+++ b/net/minecraft/world/level/block/HopperBlock.java
@@ -133,6 +133,14 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
index a4b824dab307705559a76b954a3e47d30dd65889..bc036d8e9d241ea9178808fce39c4e5115d5f753 100644
--- a/net/minecraft/world/level/block/JukeboxBlock.java
+++ b/net/minecraft/world/level/block/JukeboxBlock.java
@@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof JukeboxBlockEntity jukeboxBlockEntity) {
+ jukeboxBlockEntity.popOutTheItem();
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
index 52b9bd310c731c407fc4264559084debec81d3d9..0b991825d48ad64c1c68fd7c6bded7583572dded 100644
--- a/net/minecraft/world/level/block/LecternBlock.java
+++ b/net/minecraft/world/level/block/LecternBlock.java
@@ -198,6 +198,36 @@ public class LecternBlock extends BaseEntityBlock {
changePowered(level, pos, state, false);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(HAS_BOOK)) {
+ this.popBook(state, level, pos);
+ }
+
+ if (state.getValue(POWERED)) {
+ updateBelow(level, pos, state);
+ }
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+
+ private void popBook(BlockState state, Level level, BlockPos pos) {
+ if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already // Leaves - the method with validate arg already removed by paper...
+ Direction direction = state.getValue(FACING);
+ ItemStack itemStack = lecternBlockEntity.getBook().copy();
+ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
+ float f = 0.25F * direction.getStepX();
+ float f1 = 0.25F * direction.getStepZ();
+ net.minecraft.world.entity.item.ItemEntity itemEntity = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack);
+ itemEntity.setDefaultPickUpDelay();
+ level.addFreshEntity(itemEntity);
+ lecternBlockEntity.clearContent();
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
index 5f03e9fed3d4a8c3b72ca05be0b62ef45ac291f7..359fe5d611bcebe4cb98b9d8cea26b255adb167e 100644
--- a/net/minecraft/world/level/block/LeverBlock.java
+++ b/net/minecraft/world/level/block/LeverBlock.java
@@ -124,6 +124,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
index dbfe086123c4b3cdc866111e1b6ec37d8d38d394..adad6e538b128729b72b7d44cabbd0cfba7417f9 100644
--- a/net/minecraft/world/level/block/LightningRodBlock.java
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
@@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
index 3c12d8e23f20b666b0005e597ba2e803c02d5d78..17c371f4c24e8a81705bdd322b1de5de4b8be8b7 100644
--- a/net/minecraft/world/level/block/ObserverBlock.java
+++ b/net/minecraft/world/level/block/ObserverBlock.java
@@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
+ this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.FALSE));
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 48f9e234e4025633cbc41d334d88ada36c2e0d7b..5c154d15e5aa45988436722595c7fca74e166c9a 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -368,6 +368,27 @@ public class RedStoneWireBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ for (Direction direction : Direction.values()) {
+ level.updateNeighborsAt(pos.relative(direction), this);
+ }
+
+ // Paper start - optimize redstone - replace call to updatePowerStrength
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
+ } else {
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
+ }
+ // Paper end - optimize redstone
+ this.updateNeighborsOfNeighboringWires(level, pos);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
index d1dbfc821f068f14bf975842f66251816ea5c985..fe13504a7d2d685e43183dd7b3219f1605570adb 100644
--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java
+++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java
@@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving) {
+ this.notifyNeighbors(level, pos, state);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
index 80e6ba8f026a6565696f18304507b2d0a347650c..593fab3d2a70bcd6832dd777afa4973f22abbaeb 100644
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -128,6 +128,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (getPhase(state) == SculkSensorPhase.ACTIVE) {
+ updateNeighbours(level, pos, state);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
index 2815fb48530de3a2f9ef0f472a0fd0a2c32140b6..6b5e5bbbeb11bd8ce100ef3c215dfcf4b387e595 100644
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
super.stepOn(level, pos, state, entity);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) {
+ serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel));
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (state.getValue(SHRIEKING)) {
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 77840814806c7d07b58cd716cf7ec095e894498a..e820cd03e695649a8f83e23ae822524a8f78e23b 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -150,6 +150,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
// Paper end - re-set loot table if it was cleared
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof ShulkerBoxBlockEntity) {
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
+ }
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
index 9d005c3db8f0c784cdd7217e7b110daa703a9cf3..190d7cd818f768bd44fc1b4e62af2c9b3aacbe4d 100644
--- a/net/minecraft/world/level/block/TripWireBlock.java
+++ b/net/minecraft/world/level/block/TripWireBlock.java
@@ -108,6 +108,16 @@ public class TripWireBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
+ if (!isMoving && !state.is(newState.getBlock())) {
+ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE));
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
index 42a5e9a7f5d604e4821a116ba13319df052faf97..e90e142cfb15335522a48ad82aa90018ed8ec349 100644
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -244,6 +244,25 @@ public class TripWireHookBlock extends Block {
level.updateNeighborsAt(pos.relative(opposite), block, orientation);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ boolean attachedValue = state.getValue(ATTACHED);
+ boolean poweredValue = state.getValue(POWERED);
+ if (attachedValue || poweredValue) {
+ calculateState(level, pos, state, true, false, -1, null);
+ }
+
+ if (poweredValue) {
+ notifyNeighbors(this, level, pos, state.getValue(FACING));
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java
index 6a9d23d25a79c73d5792011faf0e5a1c4c25bc64..84e0d3cd3c349f0d588a4b4c2d6844480a92b4ca 100644
--- a/net/minecraft/world/level/block/entity/BlockEntityType.java
+++ b/net/minecraft/world/level/block/entity/BlockEntityType.java
@@ -306,7 +306,7 @@ public class BlockEntityType<T extends BlockEntity> {
}
public boolean isValid(BlockState state) {
- return this.validBlocks.contains(state.getBlock());
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour || this.validBlocks.contains(state.getBlock()); // Leaves - behaviour 1.21.1-
}
@Deprecated
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index 58b78e6b9a43605940420d8cb0f1163ee3f0a5ff..eebf03ece11052f07702951b9335bc151e160848 100644
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -65,6 +65,18 @@ public class MovingPistonBlock extends BaseEntityBlock {
return createTickerHelper(blockEntityType, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof PistonMovingBlockEntity) {
+ ((PistonMovingBlockEntity)blockEntity).finalTick();
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
public void destroy(LevelAccessor level, BlockPos pos, BlockState state) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index b369e80a4fc371a3762e34e7d4d180b86d1d190f..0b412e360b090dc85d1726eb8f51c69b47061276 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
return super.playerWillDestroy(level, pos, state, player);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
+ if (this.isFittingBase(state, level.getBlockState(blockPos))) {
+ level.destroyBlock(blockPos, true);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4daf68cfd3 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -171,6 +171,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
}
+ // Leaves start - behaviour 1.21.1-
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
+ if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
+ level.removeBlockEntity(pos);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
}
@@ -866,6 +875,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
// CraftBukkit end
}
+ // Leaves start - behaviour 1.21.1-
+ public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) {
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 5551d80a81c2878136f96b3e695c4888c7105a49..73dd8e67938fbfff745b189c06a93174976ba1bf 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -406,22 +406,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
boolean flag = !blockState.is(block);
boolean flag1 = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0;
boolean flag2 = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0;
- if (flag && blockState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(blockState)) {
- if (!this.level.isClientSide() && flag2) {
- BlockEntity blockEntity = this.level.getBlockEntity(pos);
- if (blockEntity != null) {
- blockEntity.preRemoveSideEffects(pos, blockState);
+ // Leaves start - behaviour 1.21.1-
+ if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) {
+ if (flag && blockState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(blockState)) {
+ if (!this.level.isClientSide() && flag2) {
+ BlockEntity blockEntity = this.level.getBlockEntity(pos);
+ if (blockEntity != null) {
+ blockEntity.preRemoveSideEffects(pos, blockState);
+ }
}
- }
- this.removeBlockEntity(pos);
- }
+ this.removeBlockEntity(pos);
+ }
- if ((flag || block instanceof BaseRailBlock)
- && this.level instanceof ServerLevel serverLevel
- && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ if ((flag || block instanceof BaseRailBlock)
+ && this.level instanceof ServerLevel serverLevel
+ && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) {
+ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ }
+ } else {
+ blockState.onRemove(this.level, pos, state, flag1);
}
+ // Leaves end - behaviour 1.21.1-
if (!section.getBlockState(i, i1, i2).is(block)) {
return null;
@@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 23:26:27 +0800
Subject: [PATCH] Leaves: Do not reset placed block on exception & Do not
prevent block entity and entity crash at LevelChunk
Co-authored by: MC_XiaoHei <xiaohei.xor7@outlook.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index a5d3caab2072b2c9bf8fdcbdb7c52c2dee16cfaf..4bb36d2965785fadf628a9bfac4fa2aa305aaf65 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -77,20 +77,22 @@ public class BlockItem extends Item {
BlockState blockState = level.getBlockState(clickedPos);
if (blockState.is(placementState.getBlock())) {
blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState);
+ // Leaves start - we do not need this
// Paper start - Reset placed block on exception
- try {
+ // try {
this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState);
updateBlockEntityComponents(level, clickedPos, itemInHand);
- } catch (Exception ex) {
- ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
- if (player instanceof ServerPlayer serverPlayer) {
- org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
- serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
- return InteractionResult.FAIL;
- }
- throw ex; // Rethrow exception if not placed by a player
- }
+ // } catch (Exception ex) {
+ // ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
+ // if (player instanceof ServerPlayer serverPlayer) {
+ // org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
+ // serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
+ // return InteractionResult.FAIL;
+ // }
+ // throw ex; // Rethrow exception if not placed by a player
+ // }
// Paper end - Reset placed block on exception
+ // Leaves end - we dot not need this
blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand);
// CraftBukkit start
if (bukkitState != null) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 73dd8e67938fbfff745b189c06a93174976ba1bf..8e56c2237f9d49d0b09b62c0933283f77aaae679 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1001,12 +1001,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
profilerFiller.pop();
} catch (Throwable var5) {
+ // Leaves start - do not prevent here
// Paper start - Prevent block entity and entity crashes
- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
- net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
- net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
- LevelChunk.this.removeBlockEntity(this.getPos());
+ // final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
+ // net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
+ // net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
+ // LevelChunk.this.removeBlockEntity(this.getPos());
// Paper end - Prevent block entity and entity crashes
+ // Leaves end - do not prevent here
}
}
}
@@ -0,0 +1,136 @@
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,
@@ -0,0 +1,51 @@
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,18 @@
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,7 +8,7 @@ Helvetica Volubi <suisuroru@blue-millennium.fun>
bdlvl <bdlvl@blendreams.cn>
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
index 22c038e6556d9911e1eaedf71d7b86843af89c16..f5574eb883b1ee8747acc42832bc88ae03e27b67 100644
index fcdfd4f6de5e1c2d5e80c7f3d8cb0b33a62d257d..6eaa4e9bd1ecbfa531313ce1f470d55edf31b467 100644
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
+++ b/src/main/java/com/destroystokyo/paper/Metrics.java
@@ -593,7 +593,7 @@ public class Metrics {
@@ -35,27 +35,20 @@ index 22c038e6556d9911e1eaedf71d7b86843af89c16..f5574eb883b1ee8747acc42832bc88ae
metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> {
Map<String, Map<String, Integer>> map = new HashMap<>();
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
index 22125dbe1765f930fe10fe420be1c275ec553139..d5b070d1a3d84e228960dacd614e0f1abe968e79 100644
index a5f2e4454258886536251288c3694f58386c7420..28371ecf31d5fc280aaa03ed9a86f5b565cf32f6 100644
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
@@ -35,7 +35,7 @@ public class PaperVersionFetcher implements VersionFetcher {
private static final Logger LOGGER = LogUtils.getClassLogger();
@@ -40,8 +40,8 @@ public class PaperVersionFetcher implements VersionFetcher {
private static final ComponentLogger COMPONENT_LOGGER = ComponentLogger.logger(LogManager.getRootLogger().getName());
private static final int DISTANCE_ERROR = -1;
private static final int DISTANCE_UNKNOWN = -2;
- private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Luminol"; //Luminol
+ private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Lophine"; //Luminol // Lophine
@Override
public long getCacheTime() {
@@ -49,7 +49,7 @@ public class PaperVersionFetcher implements VersionFetcher {
if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) {
updateMessage = text("You are running a development version without access to version information", color(0xFF5300));
} else {
- updateMessage = getUpdateStatusMessage("LuminolMC/Luminol", build); // Folia // Luminol
+ updateMessage = getUpdateStatusMessage("LuminolMC/Lophine", build); // Folia // Luminol // Lophine
}
final @Nullable Component history = this.getHistory();
- private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Luminol"; // Luminol
- private static final String REPOSITORY = "LuminolMC/Luminol"; // Luminol
+ private static final String DOWNLOAD_PAGE = "https://github.com/LuminolMC/Lophine"; // Luminol // Lophine
+ private static final String REPOSITORY = "LuminolMC/Lophine"; // Luminol // Lophine
private static final ServerBuildInfo BUILD_INFO = ServerBuildInfo.buildInfo();
private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://papermc.io)";
private static final Gson GSON = new Gson();
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5effe76734b4 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
@@ -90,19 +83,6 @@ index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5eff
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..2c546d470013d4daf3ddf427ab4bda1b51d6e641 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
@@ -11,7 +11,7 @@ public final class Versioning {
public static String getBukkitVersion() {
String result = "Unknown-Version";
- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.luminol/luminol-api/pom.properties"); // Folia //Luminol
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/fun.bm.lophine/lophine-api/pom.properties"); // Folia //Luminol
Properties properties = new Properties();
if (stream != null) {
diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png
index 2b6037aab645e303df6edbbc8af34dc4b4a55bc5..76ea89f23e6d2a42806c5d5d29b415d325e1ee82 100644
GIT binary patch
@@ -41,10 +41,10 @@ index 2f41a92465b9da28e026297cc3528898bb1c8412..168301a2f1c3081ae15d3695c2dcc72b
case DROPPER:
this.delegate = new DispenserMenu(windowId, bottom, top);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
index f850e6cea92edc87ed54cf54488b5ebb606913ed..f4db38de4348fb03db0b769bd5b5993184dd4abb 100644
index 9d5fe6fc727948955d89f9ed5e181185393a9611..1343972a3a230dcef7349f014a80362ffcb0fe94 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
@@ -84,7 +84,7 @@ public class CraftInventory implements Inventory {
@@ -85,7 +85,7 @@ public class CraftInventory implements Inventory {
@Override
public void setContents(ItemStack[] items) {
@@ -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/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 4dde33c872d463bf17ba03e926de90e6988444b2..de72f36bd22e2c7452b9c3ee40657f6119ca70b3 100644
index 507204301b5e3cd545e66c510842c0a6391f0241..dfcfc83474443638e30f87d54472e5a38947dfad 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -497,6 +497,7 @@ public final class CraftServer implements Server {
@@ -485,6 +485,7 @@ public final class CraftServer implements Server {
this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
if (false) this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark // Luminol - Force disable builtin spark
@@ -19,7 +19,7 @@ index 4dde33c872d463bf17ba03e926de90e6988444b2..de72f36bd22e2c7452b9c3ee40657f61
}
public boolean getCommandBlockOverride(String command) {
@@ -1115,6 +1116,7 @@ public final class CraftServer implements Server {
@@ -1059,6 +1060,7 @@ public final class CraftServer implements Server {
if (false) this.spark.registerCommandBeforePlugins(this); // Paper - spark // Luminol - Force disable builtin spark
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
@@ -0,0 +1,13 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 16 Nov 2025 17:47:42 +0800
Subject: [PATCH] LeavesHooks
diff --git a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
index e57c3ca79677b1dfe7cf3db36f0406de7ea5bd0a..86edd824ec42e550dd1419fd57d93a21fe2d648d 100644
--- a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
+++ b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
@@ -1 +1 @@
-ca.spottedleaf.moonrise.paper.PaperHooks
+org.leavesmc.leaves.region.LeavesHooks
@@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 22 Nov 2025 01:43:26 +0800
Subject: [PATCH] Add cancel task by task id in FoliaGlobalRegionScheduler
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
index 14ffbcb66006878eacf310547dad53718f8308eb..6c108bc7d93196803daeef4751d06cafa6eeec1a 100644
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
@@ -16,6 +16,8 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private long tickCount = 0L;
private final Object stateLock = new Object();
private final Long2ObjectOpenHashMap<List<GlobalScheduledTask>> tasksByDeadline = new Long2ObjectOpenHashMap<>();
+ private int lastTaskId = 1; // Lophine - add task id
+ private final Object stateLockForTaskId = new Object(); // Lophine - add task id
public void tick() {
final List<GlobalScheduledTask> run;
@@ -64,7 +66,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, delayTicks);
@@ -91,7 +93,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, initialDelayTicks);
@@ -133,7 +135,33 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
- private final class GlobalScheduledTask implements ScheduledTask, Runnable {
+ // Lophine start - add cancel task by task id
+ public void cancelTask(final int taskId) {
+ synchronized (this.stateLock) {
+ for (final List<GlobalScheduledTask> tasks : this.tasksByDeadline.values()) {
+ for (final GlobalScheduledTask task : tasks) {
+ if (task.getTaskId() == taskId) {
+ task.cancel();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private int getNextTaskId() {
+ synchronized (this.stateLockForTaskId) {
+ if (this.lastTaskId == Integer.MAX_VALUE) {
+ this.lastTaskId = 1;
+ } else {
+ ++this.lastTaskId;
+ }
+ }
+ return this.lastTaskId;
+ }
+ // Lophine end - add cancel task by task id
+
+ public final class GlobalScheduledTask implements ScheduledTask, Runnable { // Lophine - private -> public
private static final int STATE_IDLE = 0;
private static final int STATE_EXECUTING = 1;
@@ -145,13 +173,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 static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
- private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run) {
+ private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run, int taskId) { // Lophine - add task id
this.plugin = plugin;
this.repeatDelay = repeatDelay;
this.run = run;
+ this.taskId = taskId; // Lophine - add task id
}
private final int getStateVolatile() {
@@ -262,5 +292,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
}
+
+ // Lophine start - add task id
+ public int getTaskId() {
+ return taskId;
+ }
+ // Lophine end - add task id
}
}
@@ -41,22 +41,22 @@ index 9180f23529a31b6b0a5b38bb7cda3e32d487f691..e1f456b31ffda9370b63e51f343847d6
if (!registration.getPlugin().isEnabled()) {
continue;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0a10f49ee410d93e95ceb90108200a1a9d12b54b..d2eee37d810a6d5cf514bc71dea66a4d2b0d09e2 100644
index 21d594a39d09b2d17f05c40ce5323d57949d0b0b..46859fc70795097366f02dba48fdaab8b9c85013 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -423,6 +423,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
@@ -374,6 +374,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
@SuppressWarnings("unchecked")
public <T extends Entity> T addEntity(T entity) {
Preconditions.checkArgument(!entity.isInWorld(), "Entity has already been added to a world");
+ Preconditions.checkState(!(entity instanceof org.leavesmc.leaves.entity.bot.CraftBot), "[Leaves] Fakeplayers do not support changing world, Please use leaves fakeplayer-api instead!");
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle();
if (nmsEntity.level() != this.getHandle().getLevel()) {
nmsEntity = nmsEntity.teleport(new TeleportTransition(this.getHandle().getLevel(), nmsEntity, TeleportTransition.DO_NOTHING));
throw new IllegalArgumentException(entity + " wasn't created with this world, you must create the entity with the world you want to add it to.");
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c3c89e815 100644
index dfcfc83474443638e30f87d54472e5a38947dfad..973f064fc5e089dc892d4b4077a807517fd199b5 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -316,6 +316,7 @@ public final class CraftServer implements Server {
@@ -305,6 +305,7 @@ public final class CraftServer implements Server {
private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer;
public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
private final ServerConfiguration serverConfig = new PaperServerConfiguration();
@@ -64,7 +64,7 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
// Paper start - Folia region threading API
private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
@@ -498,6 +499,7 @@ public final class CraftServer implements Server {
@@ -486,6 +487,7 @@ public final class CraftServer implements Server {
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
if (false) this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark // Luminol - Force disable builtin spark
org.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol
@@ -72,7 +72,7 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
}
public boolean getCommandBlockOverride(String command) {
@@ -1482,7 +1484,7 @@ public final class CraftServer implements Server {
@@ -1379,7 +1381,7 @@ public final class CraftServer implements Server {
return false;
}
@@ -81,7 +81,7 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
return false;
}
@@ -3260,6 +3262,13 @@ public final class CraftServer implements Server {
@@ -3041,6 +3043,13 @@ public final class CraftServer implements Server {
this.console.addPluginAllowingSleep(plugin.getName(), value);
}
@@ -96,10 +96,10 @@ index de72f36bd22e2c7452b9c3ee40657f6119ca70b3..0a96721797b9bbc643f68677bbb1d10c
/**
* Gets the TPS from the region which owns the specified location, or {@code null} if no region owns
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e2630a29409 100644
index dcd32c1e32fd67ec13bb7fca8af20aa665407594..b7f83e66227b5a1f5ad9b424e425eee118cc0692 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -249,7 +249,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@@ -247,7 +247,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public int getPlayerCount() {
@@ -108,7 +108,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
}
@Override
@@ -1279,9 +1279,9 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@@ -1121,9 +1121,9 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public List<Player> getPlayers() {
@@ -120,7 +120,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
HumanEntity bukkitEntity = human.getBukkitEntity();
if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) {
@@ -1988,7 +1988,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@@ -1622,7 +1622,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public void playSound(final net.kyori.adventure.sound.Sound sound) {
org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
final long seed = sound.seed().orElseGet(this.world.getRandom()::nextLong);
@@ -129,7 +129,7 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player.getX(), player.getY(), player.getZ(), seed, null));
}
}
@@ -2016,7 +2016,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@@ -1650,7 +1650,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper
final long seed = sound.seed().orElseGet(this.getHandle().getRandom()::nextLong);
if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) {
@@ -138,20 +138,20 @@ index 9b9eea4babcd67a088e9400b369d168d11c06ac1..3177db282013e6dc3c7215fc2a851e26
player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player, seed, null));
}
} else if (emitter instanceof CraftEntity craftEntity) {
@@ -2248,7 +2248,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@@ -1791,7 +1791,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType());
}
this.getHandle().sendParticlesSource(
- receivers == null ? this.getHandle().players() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API
+ receivers == null ? this.getHandle().realPlayers() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API // Leaves - skip
- receivers == null ? this.getHandle().players() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API
+ receivers == null ? this.getHandle().realPlayers() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API // Leaves - skip
sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API
CraftParticle.createParticleParam(particle, data), // Particle
force,
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 852e1ffef6a022caad7c8eff34091e50112a2290..8eb5d014d9ed688ffebaffb4ce0bb40896961a04 100644
index e6cd1c4a50b32b74f70a264e869b1ab4ac9b9eb0..6867064de52d810f1fd3869463ae27868ed0fb07 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -126,6 +126,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@@ -127,6 +127,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return new CraftHumanEntity(server, (net.minecraft.world.entity.player.Player) entity);
}
@@ -161,10 +161,10 @@ index 852e1ffef6a022caad7c8eff34091e50112a2290..8eb5d014d9ed688ffebaffb4ce0bb408
if (entity instanceof EnderDragonPart complexPart) {
if (complexPart.parentMob instanceof EnderDragon) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e040f9a7c9451fbe547dda56952410047a99ddc0..05753de195bd7f4ac2952183662a8cc9ec8f4ba0 100644
index 0429ffda4aa4410f6f53bd163be8dee71b134637..9274f4ef639ed9b3028321566173d6612663082b 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -897,7 +897,11 @@ public class CraftEventFactory {
@@ -1014,7 +1014,11 @@ public class CraftEventFactory {
event.setKeepInventory(keepInventory);
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
populateFields(victim, event); // Paper - make cancellable
@@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 16 Nov 2025 15:55:47 +0800
Subject: [PATCH] Leaves: Replay Mod API
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 100644
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
@@ -57,7 +57,7 @@ class PaperEventManager {
}
// Leaves start - skip bot
- if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot) {
+ if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && (playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot || playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.photographer.Photographer)) { // Leaves - and photographer
return;
}
// Leaves end - skip bot
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 973f064fc5e089dc892d4b4077a807517fd199b5..06766a9058595aeee25e8fd3e3d01aeec2a55116 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 {
public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
private final ServerConfiguration serverConfig = new PaperServerConfiguration();
private final org.leavesmc.leaves.entity.bot.CraftBotManager botManager; // Leaves
+ private final org.leavesmc.leaves.entity.photographer.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.photographer.CraftPhotographerManager(); // Leaves
// Paper start - Folia region threading API
private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
@@ -400,7 +401,7 @@ public final class CraftServer implements Server {
public CraftServer(DedicatedServer console, PlayerList playerList) {
this.console = console;
this.playerList = (DedicatedPlayerList) playerList;
- this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<ServerPlayer, CraftPlayer>() {
+ this.playerView = Collections.unmodifiableList(Lists.transform(playerList.realPlayers, new Function<ServerPlayer, CraftPlayer>() { // Leaves - replay api
@Override
public CraftPlayer apply(ServerPlayer player) {
return player.getBukkitEntity();
@@ -3114,4 +3115,11 @@ public final class CraftServer implements Server {
}
}
// Folia end - region TPS API
+
+ // Leaves start - replay mod api
+ @Override
+ public org.leavesmc.leaves.entity.photographer.CraftPhotographerManager getPhotographerManager() {
+ return photographerManager;
+ }
+ // Leaves end - replay mod api
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 6867064de52d810f1fd3869463ae27868ed0fb07..69a0de762cfde089e8aaa6e6be79a8c8298d7778 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -128,6 +128,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { return new org.leavesmc.leaves.entity.bot.CraftBot(server, bot); }
+ if (entity instanceof org.leavesmc.leaves.replay.ServerPhotographer photographer) { return new org.leavesmc.leaves.entity.photographer.CraftPhotographer(server, photographer); }
// Special case complex part, since there is no extra entity type for them
if (entity instanceof EnderDragonPart complexPart) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 6e745c7ddf417ec2fdcf102edd6a592047b5f73e..2f59107642d43719159872d5df37107d8a1a5b97 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
@Override
public boolean canSee(Player player) {
- return this.canSee((org.bukkit.entity.Entity) player);
+ return !(player instanceof org.leavesmc.leaves.entity.photographer.Photographer) && this.canSee((org.bukkit.entity.Entity) player); // Leaves - skip photographer
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 6f608ad5d1151925ad0f38596dfe15290d20d753..9c1a48dd4a8957200d8c05cf7e142c621132bb74 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 {
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
}
- MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> {
+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().realPlayers.forEach(player -> { // Leaves - only real players
player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements());
player.getAdvancements().flushDirty(player, false);
});
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
index 25aae550dcdcef2df268d0dd99bdcc9bbd49fcf8..83af50de50a03e164d572f3c3466b6d0b42ed138 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
@@ -23,7 +23,7 @@ public class LazyPlayerSet extends LazyHashSet<Player> {
}
public static Set<Player> makePlayerSet(final MinecraftServer server) {
- List<ServerPlayer> players = server.getPlayerList().players;
+ List<ServerPlayer> players = server.getPlayerList().realPlayers; // Leaves - only real players
Set<Player> reference = new HashSet<>(players.size());
for (ServerPlayer player : players) {
reference.add(player.getBukkitEntity());
@@ -0,0 +1,8 @@
package fun.bm.lophine;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
public class LophineLogger {
public static final Logger LOGGER = LogUtils.getLogger();
}
@@ -0,0 +1,41 @@
package fun.bm.lophine.command.counter;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.command.counter.sub.DisplayCommand;
import fun.bm.lophine.command.counter.sub.ResetCommand;
import fun.bm.lophine.command.counter.sub.ToggleCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.RootNode;
import org.leavesmc.leaves.util.HopperCounter;
public class CounterCommand extends RootNode {
private final String PERM_BASE;
public CounterCommand() {
super("counter", "lophine.commands.counter");
this.PERM_BASE = "lophine.commands.counter";
children(
new ToggleCommand(this),
new ResetCommand(this),
new DisplayCommand(this)
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
Component.text("Hopper Counter: ", NamedTextColor.GRAY),
Component.text(HopperCounter.isEnabled(), HopperCounter.isEnabled() ? NamedTextColor.AQUA : NamedTextColor.GRAY)
));
return true;
}
public boolean hasPermission(@NotNull CommandSender sender, String... subcommand) {
return hasPermission(PERM_BASE, sender, subcommand);
}
}
@@ -0,0 +1,24 @@
package fun.bm.lophine.command.counter;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.LiteralNode;
public class CounterSubCommand extends LiteralNode {
protected final CounterCommand parent;
protected CounterSubCommand(String name, CounterCommand parent) {
super(name);
this.parent = parent;
}
@Override
public boolean requires(@NotNull CommandSourceStack source) {
return hasPermission(source.getSender());
}
protected boolean hasPermission(CommandSender sender) {
return parent.hasPermission(sender, this.name);
}
}
@@ -0,0 +1,91 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.DyeColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
import java.util.concurrent.CompletableFuture;
public class DisplayCommand extends CounterSubCommand {
public DisplayCommand(CounterCommand parent) {
super("display", parent);
children(
DyeColorArg::new
);
}
public static void displayCounter(CommandContext context, @NotNull HopperCounter counter, boolean realTime) {
for (Component component : counter.format(MinecraftServer.getServer(), realTime)) {
context.getSender().sendMessage(component);
}
}
private static class DyeColorArg extends ArgumentNode<String> {
protected DyeColorArg() {
super("color", StringArgumentType.string());
children(
TimeArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
displayCounter(context, counter, false);
return true;
}
@Override
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
for (DyeColor value : DyeColor.values()) {
String color = value.getName();
if (color.startsWith(path)) {
builder.suggest(color);
}
}
return builder.buildFuture();
}
private static class TimeArg extends ArgumentNode<String> {
protected TimeArg() {
super("time", StringArgumentType.string());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
String timeType = context.getArgument(TimeArg.class);
switch (timeType) {
case "realtime" -> displayCounter(context, counter, true);
case "gametick" -> displayCounter(context, counter, false);
default ->
context.getSender().sendMessage(Component.text("Invalid time type: " + timeType, NamedTextColor.RED));
}
return true;
}
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
builder.suggest("realtime");
builder.suggest("gametick");
return builder.buildFuture();
}
}
}
}
@@ -0,0 +1,76 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.format.TextColor;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.item.DyeColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
import java.util.concurrent.CompletableFuture;
public class ResetCommand extends CounterSubCommand {
public ResetCommand(CounterCommand parent) {
super("reset", parent);
children(
DyeColorArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
HopperCounter.resetAll(MinecraftServer.getServer(), false);
context.getSender().sendMessage(Component.text("Restarted all counters."));
return true;
}
private static class DyeColorArg extends ArgumentNode<String> {
protected DyeColorArg() {
super("color", StringArgumentType.string());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
String color0 = context.getArgument(DyeColorArg.class);
if (color0.equals("all")) {
HopperCounter.resetAll(MinecraftServer.getServer(), false);
context.getSender().sendMessage(Component.text("Restarted all counters."));
return true;
}
DyeColor color = DyeColor.byName(color0, null);
if (color == null) return true;
HopperCounter counter = HopperCounter.getCounter(color);
counter.reset(MinecraftServer.getServer());
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
Component.text("Restarted "),
Component.text(color.getName(), TextColor.color(color.getTextColor())),
Component.text(" counter.")
));
return true;
}
@Override
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
if ("all".startsWith(path)) {
builder.suggest("all");
}
for (DyeColor value : DyeColor.values()) {
String color = value.getName();
if (color.startsWith(path)) {
builder.suggest(color);
}
}
return builder.buildFuture();
}
}
}
@@ -0,0 +1,55 @@
package fun.bm.lophine.command.counter.sub;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.command.counter.CounterCommand;
import fun.bm.lophine.command.counter.CounterSubCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.util.HopperCounter;
public class ToggleCommand extends CounterSubCommand {
public ToggleCommand(CounterCommand parent) {
super("toggle", parent);
children(
BooleanArg::new
);
}
@Override
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
if (!HopperCounter.isEnabled()) {
HopperCounter.setEnabled(true);
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
} else {
HopperCounter.setEnabled(false);
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
}
return true;
}
private static class BooleanArg extends ArgumentNode<Boolean> {
protected BooleanArg() {
super("enabled", BoolArgumentType.bool());
}
@Override
protected boolean execute(@NotNull CommandContext context) {
boolean enabled = context.getArgument(BooleanArg.class);
if (enabled == HopperCounter.isEnabled()) {
context.getSender().sendMessage(Component.text("Hopper Counter is already " + (enabled ? "enabled" : "disabled") + ".", NamedTextColor.GRAY));
} else {
HopperCounter.setEnabled(enabled);
if (enabled) {
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
} else {
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
}
}
return true;
}
}
}
@@ -13,12 +13,6 @@ public class CommandConfig implements IConfigModule {
Allow to use tick command""")
public static boolean tick = false;
@ConfigInfo(name = "datapack_command_enabled", comments =
"""
Allow to use datapack command
--- datapack hot-update unsupported, please restart server""")
public static boolean datapack = false;
@ConfigInfo(name = "function_command_enabled", comments =
"""
Allow to use function command""")
@@ -28,11 +22,21 @@ public class CommandConfig implements IConfigModule {
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
@ConfigInfo(name = "waypoint_command_enabled", comments =
"""
Allow to use waypoint command""")
Allow to use waypoint command and locator bar""")
public static boolean waypoint = false;
@ConfigInfo(name = "scoreboard_command_enabled", comments =
"""
Allow to use scoreboard command""")
public static boolean scoreboard = false;
@ConfigInfo(name = "enabled", directory = {"save_all_command"}, comments =
"""
Allow to use save-all command""")
public static boolean saveAll = false;
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"}, comments =
"""
Log all process of save-all command to console""")
public static boolean logAllProcess = false;
}
@@ -0,0 +1,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.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(name = "global_entities_counter", category = EnumConfigCategory.EXPERIMENT)
public class GlobalEntitiesCounter implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "enabled", comments = """
Enable global entities counter.
You need to set per-player-mob-spawns to false on paper-world-defaults.yml or paper-world.yml""")
public static boolean enabled = false;
@HotReloadUnsupported
@ConfigInfo(name = "async", comments = "Enable Asynchronous(maybe cause bugs)")
public static boolean async = false;
}
@@ -0,0 +1,34 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
/*
* This is a config module for redstone in experimental level
* If we think configs from here is stable for future, we will move them to function module directory
*/
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@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;
}
@@ -1,15 +0,0 @@
package fun.bm.lophine.config.modules.fixes;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "end-void-ring")
public class EndVoidRingsConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"gameplay", "end_void_rings"})
@ConfigInfo(name = "enabled", comments = """
If enabled, it will generate end void rings, like MC-159283.""")
public static boolean enabled = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.fixes;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "update-suppression-crash-fix")
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Should crash caused by update suppression be prevented?""")
public static boolean enabled = true;
}
@@ -23,14 +23,16 @@ public class ContainerExpansionConfig implements IConfigModule {
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", comments =
@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")
@ConfigInfo(name = "same_nbt_shulker_stackable", directory = {"shulker_box"})
public static boolean nbtShulkerStackable = false;
}
@@ -5,10 +5,12 @@ import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.bot.BotCommand;
import java.util.List;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@@ -91,7 +93,7 @@ public class FakeplayerConfig implements IConfigModule {
}
@Override
public void onLoaded(CommentedFileConfig configInstance) {
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enable) {
command = new BotCommand();
command.register();
@@ -24,4 +24,12 @@ public class OldFeatureConfig implements IConfigModule {
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", directory = {"misc", "revert_raid_changes"}, transformComments = false)
@ConfigInfo(name = "old_raid_behavior")
public static boolean oldRaidBehavior = false;
@TransformedConfig(name = "villager-infinite-trade", directory = {"function", "villager"}, transformComments = false)
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager"}, transformComments = false)
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager-config"}, transformComments = false)
@ConfigInfo(name = "villager-void-trade", comments =
"""
Allow villager void trade.""")
public static boolean villagerVoidTrade = false;
}
@@ -0,0 +1,34 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.utils.RandomProfilePool;
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.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "replay-api")
public class ReplayAPIConfig implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "enable-cache")
public static boolean enableCache = true;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-time", comments = """
Time to cache photographer profile(in seconds)""")
public static int cachePhotographerTime = 3600;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-size", comments = """
Maximum size of cache photographer profile""")
public static int cachePhotographerSize = 100;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
RandomProfilePool.init();
}
}
@@ -1,19 +0,0 @@
package fun.bm.lophine.config.modules.function;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "villager")
public class VillagerConfig implements IConfigModule {
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager"})
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager-config"})
@ConfigInfo(name = "villager-infinite-trade", comments =
"""
Allow villager infinite trade (limit of 524288 times)
---- we won't edit saved data, only edit in send data to client.
(after we fixed void trade, this config will drop to void trade)""")
public static boolean villagerInfiniteTrade = false;
}
@@ -0,0 +1,31 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.command.counter.CounterCommand;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
public class WoolHopperCounterConfig implements IConfigModule {
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "unlimited-speed")
public static boolean unlimitedSpeed = false;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
if (enabled) new CounterCommand().register();
}
@Override
public void onUnloaded(CommentedFileConfig configInstance) {
Bukkit.getCommandMap().getKnownCommands().remove("luminol:tpsbar");
}
}
@@ -0,0 +1,23 @@
package fun.bm.lophine.config.modules.function.protocol;
import fun.bm.lophine.enums.EnumAlternativePlaceType;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "alternative_block_placement", directory = {"protocol"})
public class AlternativeBlockPlacementProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Specify the precise placement protocol type
NONE Disable precise placement protocol
CARPET Precise placement protocol version 2
CARPET_FIX Enhanced precise placement protocol version 2 (requires MasaGadget installed on client)
LITEMATICA Precise placement protocol version 3""")
public static EnumAlternativePlaceType alternativeBlockPlacement = EnumAlternativePlaceType.NONE;
public static boolean needIgnoreDistance() {
return alternativeBlockPlacement != EnumAlternativePlaceType.NONE;
}
}
@@ -0,0 +1,16 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "appleskin", directory = {"protocol"})
public class AppleSkinProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable AppleSkin protocol support""")
public static boolean enabled = false;
@ConfigInfo(name = "sync-tick-interval", comments = """
Set AppleSkin Synchronization Frequency (Unit: Game Ticks)""")
public static int syncTickInterval = 20;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "bbor", directory = {"protocol"})
public class BBORProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable BBOR protocol support""")
public static boolean enabled = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "jade", directory = {"protocol"})
public class JadeProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Jade protocol support""")
public static boolean enabled = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "rei", directory = {"protocol"})
public class REIServerProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Roughly Enough Items protocol support""")
public static boolean enabled = false;
}
@@ -1,4 +1,4 @@
package fun.bm.lophine.config.modules.function;
package fun.bm.lophine.config.modules.function.protocol;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.CommandSuggestions;
@@ -9,54 +9,64 @@ import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "servux-protocol")
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "servux", directory = {"protocol"})
public class ServuxProtocolConfig implements IConfigModule {
@TransformedConfig(name = "entity-protocol", directory = {"function", "servux-protocol", "data"})
@TransformedConfig(name = "entity-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "entity-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "entity-protocol", directory = {"data"})
public static boolean entityProtocol = false;
@TransformedConfig(name = "hud-logger-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-logger-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-logger-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-logger-protocol")
public static boolean hudLoggerProtocol = false;
@TransformedConfig(name = "hud-metadata-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-metadata-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-protocol")
public static boolean hudMetadataProtocol = false;
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-metadata-share-seed", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-metadata-share-seed")
public static boolean hudMetadataShareSeed = false;
@TransformedConfig(name = "structure-protocol", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "structure-protocol", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "structure-protocol", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "structure-protocol")
public static boolean structureProtocol = false;
@TransformedConfig(name = "hud-enabled-loggers", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-enabled-loggers", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-enabled-loggers", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-enabled-loggers")
public static List<String> hudEnabledLoggers = List.of("tps", "mob_caps");
@TransformedConfig(name = "hud-update-interval", directory = {"function", "servux-protocol"})
@TransformedConfig(name = "hud-update-interval", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "hud-update-interval", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "hud-update-interval")
public static int hudUpdateInterval = 1;
@TransformedConfig(name = "litematics-enabled", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-enabled", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-enabled", directory = {"misc", "survux-protocol"})
@ConfigInfo(name = "litematics-enabled", directory = {"litematics"})
public static boolean litematicsEnabled = false;
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"function", "survux-protocol"})
@TransformedConfig(name = "litematics-max-nbt-size", directory = {"misc", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "2097152"})
@ConfigInfo(name = "litematics-max-nbt-size", directory = {"litematics"})
public static int litematicsMaxNbtSize = 2097152;
@TransformedConfig(name = "litematics-print-max-delay-ticks", directory = {"function", "servux-protocol", "litematics"})
@TransformedConfig(name = "litematics-print-max-delay-ticks", directory = {"function", "survux-protocol"})
@CommandSuggestions(suggest = {"-1", "1200"})
@ConfigInfo(name = "litematics-print-max-delay-ticks", directory = {"litematics"}, comments = "The max delay ticks for printing litematics, -1 to disable")

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