Compare commits
260 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cefaa4a712 | |||
| 322bc18e9b | |||
| fffb3115c0 | |||
| a0da7e4b51 | |||
| 2763dc8336 | |||
| 70bfb77edf | |||
| aae432fc3c | |||
| f7ad2f93f1 | |||
| 07073cb4a3 | |||
| 37c22202ab | |||
| 2e67f978ec | |||
| ed2f464914 | |||
| 1cd09226f6 | |||
| 8cd8f4fbad | |||
| e90c758a01 | |||
| e508462093 | |||
| b9c68a9b84 | |||
| 74d0b5ca5f | |||
| 4df4d07ae9 | |||
| cfc73efc9a | |||
| 0989bcaec7 | |||
| 3763d0b885 | |||
| cd3db4ae8c | |||
| 11e9760eb3 | |||
| 13c5bd7331 | |||
| bbcc103643 | |||
| a721c27e96 | |||
| 09011f05e6 | |||
| b8692e23d2 | |||
| 1bb1811027 | |||
| a4936582bb | |||
| fc760a047f | |||
| 5567b194d7 | |||
| f6f2781237 | |||
| f469ad848b | |||
| 924ab75f1d | |||
| 1b2f577e42 | |||
| 76c504e86f | |||
| 7ada14e6b6 | |||
| 24965b48c5 | |||
| 5dab6a557b | |||
| e27300d2c2 | |||
| cd665f0168 | |||
| aa07ef21ca | |||
| d50ad73a17 | |||
| 0d794003bc | |||
| 3856196543 | |||
| eff43b61ff | |||
| 06514362b8 | |||
| 5b94c79f39 | |||
| 24a315a368 | |||
| 3d54e47c5e | |||
| 6aadb1ca19 | |||
| 0a4a6baf70 | |||
| ee36fab64c | |||
| e85db692f3 | |||
| 9635e516dd | |||
| d7e1b3a6bb | |||
| 0fc9a1426d | |||
| 017e49da8a | |||
| 42d870e32b | |||
| 54ff033ef6 | |||
| 9761fde77d | |||
| e0d42cb1d3 | |||
| 559b2e089a | |||
| a07649d14d | |||
| 6aa709cf75 | |||
| 6a452799cc | |||
| e17a3f2033 | |||
| 74ac0bccf5 | |||
| f65b7f176b | |||
| 97a17dbf78 | |||
| c5194eeb8f | |||
| 58c5573421 | |||
| 1907a41329 | |||
| 21cce73216 | |||
| 163a9902cc | |||
| ba1216d4d3 | |||
| beb5cbeb52 | |||
| 5cc4371833 | |||
| 35f1e58d4d | |||
| 690d7c2785 | |||
| 115c9f8ee8 | |||
| faa3529943 | |||
| 3c3a2a6ff4 | |||
| 25776c7200 | |||
| 74e9d146e3 | |||
| a8b2972e0e | |||
| ed3063a477 | |||
| 85d2fa3372 | |||
| b22e9e588b | |||
| 90b751da5a | |||
| 7efeb48a7e | |||
| e5cc20ba9b | |||
| 46e7abe59c | |||
| 40df6b9dfb | |||
| 5559fa8bcc | |||
| 6319ddf78f | |||
| e74300a756 | |||
| d9674b4e7c | |||
| 6d02f00ac0 | |||
| 2960e7d24f | |||
| d950c6d3e8 | |||
| 357c351b95 | |||
| a780b13fcc | |||
| cf80fc6a86 | |||
| 20acc9ccf5 | |||
| e49ab25111 | |||
| eed4457419 | |||
| 429a0345d9 | |||
| 670d4e39c9 | |||
| 5d4ddb9a6b | |||
| 0ad90dc36e | |||
| 284810dfb8 | |||
| 0f67f445b9 | |||
| 018cc61204 | |||
| b9c3d8deea | |||
| 0d5b289d65 | |||
| 5b20ad2e2c | |||
| 9fcce731d0 | |||
| 0783c97224 | |||
| 300e891906 | |||
| a3e0a3ee1a | |||
| b3703e2069 | |||
| d3c8da4edb | |||
| bed0bfff06 | |||
| 238231b28b | |||
| db772aaf62 | |||
| b1bee59e6c | |||
| a9d24bd32c | |||
| f299d5188d | |||
| bbcc85fa93 | |||
| c26d8d1ee3 | |||
| 7bc12d2487 | |||
| 2c3aa4b68e | |||
| 91312b7a15 | |||
| 77c412bfe8 | |||
| c06d875df7 | |||
| 5e96851513 | |||
| 91b3ad527c | |||
| 959a1c346c | |||
| b594382a6a | |||
| 37f1b4e5f1 | |||
| af2af944bf | |||
| 54688d8e34 | |||
| 7b7f0b6d1f | |||
| 0ab3983145 | |||
| 24a9d5cea8 | |||
| 8ee77c3354 | |||
| 98df254bad | |||
| 19f001ad1b | |||
| 106dfeaa38 | |||
| 403ae2b2d0 | |||
| 96c99519d5 | |||
| 5c4031b836 | |||
| 376857ff97 | |||
| fa1ab90579 | |||
| fc9c6937b6 | |||
| 12d8ba9050 | |||
| 38a1ce0443 | |||
| a5a415e495 | |||
| b7bf1b5916 | |||
| 4a8888c578 | |||
| 2c59a32afe | |||
| cc5382977d | |||
| c07dde1c0b | |||
| 871a003a2e | |||
| d6a981a6e9 | |||
| bc166a9fb6 | |||
| feebf388f8 | |||
| dbcf764e76 | |||
| 735fe8855a | |||
| 1b45a090f6 | |||
| bb1335d390 | |||
| 00743c841f | |||
| bdb9c9dec4 | |||
| ac3653dda7 | |||
| a08fd04751 | |||
| f5debe9ee1 | |||
| 1a84d2e670 | |||
| e96891275d | |||
| 9e342c6683 | |||
| 00f7f5ee2b | |||
| 77b9582c4a | |||
| 184048fd26 | |||
| 7ccca03023 | |||
| b34fa8237e | |||
| 42a4d18717 | |||
| 2d8d7f5784 | |||
| bf509bcded | |||
| ef6759a9ab | |||
| bc1483ea7a | |||
| 5768a60ba8 | |||
| 05434f422c | |||
| 21e9299352 | |||
| 83e7718346 | |||
| 5845b976c1 | |||
| 4ca94280ae | |||
| 4cc49c6d99 | |||
| 93c0258c7e | |||
| 43a5ea0385 | |||
| 678882a435 | |||
| 8e5884147f | |||
| b999cf9f5f | |||
| 847bcd54e0 | |||
| 15a55403ff | |||
| 482809df6e | |||
| 5db8ec4bd9 | |||
| d60cd46c15 | |||
| df40d4bdc9 | |||
| 0084883933 | |||
| 1d1e4ec70b | |||
| 1927a66d8e | |||
| 38442749e7 | |||
| 70dae5976d | |||
| b08756b4b3 | |||
| 5e658adad3 | |||
| 4d6e08312a | |||
| 9efe6499d0 | |||
| 319946e8c1 | |||
| 28ce6ae7b1 | |||
| af4a8a8731 | |||
| 7059c6a062 | |||
| 98a8b65665 | |||
| ac6b1e2377 | |||
| 0e964ae71c | |||
| ba6bd9f71c | |||
| 4513cfd637 | |||
| d87cca6a97 | |||
| 79dbac2a8e | |||
| 4d3e3ac832 | |||
| d985a9ca33 | |||
| 192ef93833 | |||
| b61d6cf1ac | |||
| 1c4dea41c8 | |||
| 4740744adb | |||
| 434694f6a1 | |||
| e584866cf5 | |||
| 1cff183f26 | |||
| a3af47db18 | |||
| b830c66be7 | |||
| fc50c2ac44 | |||
| f81cee2454 | |||
| 049716a64c | |||
| c7c37c5a95 | |||
| 4dea005c0d | |||
| 074c5c9553 | |||
| f79cc86332 | |||
| e880fdecfa | |||
| dda45b510a | |||
| 6fec3a73ac | |||
| d22d5fdf5a | |||
| fcb90d468e | |||
| 1094716d9d | |||
| 3d57a67913 | |||
| ecc514b340 | |||
| 75baf3dfaf | |||
| 4ed8600511 | |||
| 0160aac4c6 | |||
| cbed24020a |
@@ -1,7 +1,7 @@
|
||||
name: Bug反馈 Bug report
|
||||
description:
|
||||
报告Bug,插件不兼容情况,以及其他相关问题。
|
||||
Report issues with plugin incompatbility or other behavior related issues.
|
||||
Report issues with plugin incompatibility or other behavior related issues.
|
||||
labels:
|
||||
- bug
|
||||
- pending
|
||||
@@ -25,7 +25,7 @@ body:
|
||||
LophineMC服务端发行版本 LophineMC server release version (contains the git commit's hash)<br>
|
||||
通过执行`/version`命令将获取到的内容复制到这里。 Run `/version` on your server and paste the full, unmodified output here.
|
||||
placeholder: >
|
||||
e.g. git-Lophine-"0635a89" (MC: 1.20.4)
|
||||
e.g. git-Lophine-"fa1ab90" (MC: 1.21.8)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -41,7 +41,7 @@ body:
|
||||
attributes:
|
||||
label: 观测到的实际行为 Observed/Actual behavior
|
||||
description: 你实际看到的。 What you actually saw.
|
||||
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
|
||||
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -65,6 +65,20 @@ body:
|
||||
To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config-file-list
|
||||
attributes:
|
||||
label: 配置文件列表(如果可以)。 Config File List (if possible).
|
||||
description:
|
||||
服务器上的配置文件列表。
|
||||
All config files on your server.
|
||||
例如以下文件(或者文件夹):
|
||||
Example files (or folders):
|
||||
- \spigot.yml
|
||||
- \bukkit.yml
|
||||
- \config\\\*
|
||||
- \lophine_config\\\*
|
||||
- \luminol_config\\\*
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
|
||||
@@ -28,7 +28,7 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: othre
|
||||
id: other
|
||||
attributes:
|
||||
label: 其他 Other
|
||||
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
|
||||
+98
-15
@@ -7,6 +7,20 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force-release:
|
||||
description: "Force disable release if you enter false, force release if you enter true, default release if not released else skip release"
|
||||
required: false
|
||||
default: ""
|
||||
force-push:
|
||||
description: "Force disable push to repo if you enter false, force push to repo if you enter true, default push if not released else skip push repo"
|
||||
required: false
|
||||
default: ""
|
||||
comments:
|
||||
description: "Add comments to release"
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions: write-all
|
||||
|
||||
@@ -14,18 +28,20 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
environment: default
|
||||
env:
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
steps:
|
||||
- name: Checkout Git Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
- name: Set Up JDK
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: zulu
|
||||
java-version: 21
|
||||
java-version: 25
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
@@ -36,36 +52,103 @@ jobs:
|
||||
- name: Apply All Patches
|
||||
run: ./gradlew --refresh-dependencies applyAllPatches
|
||||
|
||||
- name: CreateMojmapPaperclipJar
|
||||
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
|
||||
- name: Build Paperclip Jar
|
||||
run: ./gradlew --refresh-dependencies createPaperclipJar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.project_id_b }} CI Artifacts
|
||||
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
|
||||
path: lophine-server/build/libs/*-paperclip-*.jar
|
||||
|
||||
- name: SetENV
|
||||
- name: Set Environment
|
||||
if: github.event_name != 'pull_request'
|
||||
run: sh scripts/SetENV.sh
|
||||
|
||||
- name: Publish to repo
|
||||
if: github.event_name != 'pull_request' && env.flag_release == 'true' && false # do not push to any repo
|
||||
- name: Check If Release Exists
|
||||
if: github.event_name != 'pull_request' && env.flag_release == 'true'
|
||||
run: |
|
||||
git fetch --tags
|
||||
if [ -n "$(git tag -l "${{ env.tag }}")" ]; then
|
||||
echo "Release already exists"
|
||||
release_exists=true
|
||||
else
|
||||
echo "Release does not exist"
|
||||
release_exists=false
|
||||
fi
|
||||
if [ "$release_exists" == "true" ]; then
|
||||
counter=1
|
||||
while [ -n "$(git tag -l "${{ env.tag }}-${counter}")" ]; do
|
||||
counter=$((counter + 1))
|
||||
done
|
||||
echo "tag=${{ env.tag }}-${counter}" >> $GITHUB_ENV
|
||||
echo "release_count= - ${counter}" >> $GITHUB_ENV
|
||||
release_exists=false
|
||||
fi
|
||||
echo "release_exists=${release_exists}" >> $GITHUB_ENV
|
||||
|
||||
- name: Check If Branch In Expectations
|
||||
if: github.event_name != 'pull_request' && env.flag_release == 'true'
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_NAME" == ver/* ]] || [[ "$GITHUB_REF_NAME" == exp/* ]] || [[ "$GITHUB_REF_NAME" == dev/* ]]; then
|
||||
echo "Branch is in expected prefixes"
|
||||
echo "unexpect=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Branch is NOT in expected prefixes"
|
||||
echo "unexpect=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Publish To Repo
|
||||
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_push_repo == 'true' && !( inputs.force-push == 'false' )) || inputs.force-push == 'true'
|
||||
continue-on-error: true
|
||||
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
|
||||
env:
|
||||
PRIVATE_MAVEN_REPO_PASSWORD: ${{ secrets.PRIVATE_MAVEN_REPO_PASSWORD }}
|
||||
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
|
||||
|
||||
- name: Create Release
|
||||
if: github.event_name != 'pull_request' && env.flag_release == 'true'
|
||||
- name: Create Release - Pre Process
|
||||
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == 'false')) || inputs.force-release == 'true'
|
||||
run: |
|
||||
if [ "${{ inputs.comments }}" == "" ]; then
|
||||
echo "No comments provided"
|
||||
echo "flag_comment=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Comments provided: ${{ inputs.comments }}"
|
||||
echo "flag_comment=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create Release - No Comment
|
||||
if: env.flag_comment == 'false'
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ env.tag }}
|
||||
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}
|
||||
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}${{ env.release_count }}
|
||||
body: |
|
||||
📦Version: `${{ env.mcversion }}` | Commit ${{ env.commit_id }} [](https://github.com/LuminolMC/${{ env.project_id }}/releases/download/${{ env.tag }}/${{ env.jar }})
|
||||
This release is automatically compiled by GitHub Actions
|
||||
### Branch Info
|
||||
> ${{ github.ref_name }}
|
||||
### Commit Message
|
||||
${{ env.commit_msg }}
|
||||
artifacts: ${{ env.jar_dir }}
|
||||
generateReleaseNotes: true
|
||||
prerelease: ${{ env.pre }}
|
||||
makeLatest: ${{ env.make_latest }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create Release - With Comment
|
||||
if: env.flag_comment == 'true'
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ env.tag }}
|
||||
name: ${{ env.project_id_b }} ${{ env.mcversion }} - ${{ env.commit_id }}${{ env.release_count }}
|
||||
body: |
|
||||
📦Version: `${{ env.mcversion }}` | Commit ${{ env.commit_id }} [](https://github.com/LuminolMC/${{ env.project_id }}/releases/download/${{ env.tag }}/${{ env.jar }})
|
||||
This release is automatically compiled by GitHub Actions
|
||||
### Comments
|
||||
> ${{ inputs.comments }}
|
||||
### Branch Info
|
||||
> ${{ github.ref_name }}
|
||||
### Commit Message
|
||||
${{ env.commit_msg }}
|
||||
artifacts: ${{ env.jar_dir }}
|
||||
|
||||
@@ -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@v7
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
|
||||
fetch-depth: 0 # a full history is required for pull request analysis
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@latest
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1658551725 }}
|
||||
QODANA_ENDPOINT: 'https://qodana.cloud'
|
||||
+2
-4
@@ -6,12 +6,10 @@ build
|
||||
|
||||
/run
|
||||
|
||||
/lightingluminol-server/build.gradle.kts
|
||||
/lightingluminol-api/build.gradle.kts
|
||||
/luminol-server/build.gradle.kts
|
||||
/lophine-server/build.gradle.kts
|
||||
/lophine-api/build.gradle.kts
|
||||
/luminol-server/src/minecraft
|
||||
/paper-server
|
||||
/luminol-api/build.gradle.kts
|
||||
/paper-api
|
||||
/paper-api-generator
|
||||
|
||||
|
||||
@@ -1,101 +1,149 @@
|
||||
<img src="public/image/lophine/lophine3.png" alt="Logo" align="right" width="250">
|
||||
<div align="center">
|
||||
<img src="./public/image/lophine/lophine3.png" alt="Lophine Logo" width="300">
|
||||
|
||||
# Lophine
|
||||
|
||||
*Lophine 是一个基于Luminol的分支,具有许多有用的优化和可配置的原版特性,目标是在Folia上实现更多生电的内容(请注意,完整生电请使用Fabric)*
|
||||
|
||||

|
||||
[](LICENSE.md)
|
||||
[](https://github.com/LuminolMC/Lophine/issues)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
[English](./README_EN.md) | **中文**
|
||||
</div>
|
||||
|
||||
# Lophine
|
||||
---
|
||||
|
||||
<h4>Lophine 是一个基于Luminol的分支,具有许多有用的优化和可配置的原版特性,目标是在Folia上实现更多生电的实现</h4>
|
||||
## ✨ 核心特性
|
||||
|
||||
[](LICENSE.md)
|
||||
[](https://github.com/LuminolMC/Lophine/issues)
|
||||

|
||||

|
||||

|
||||
- 🔧 **可配置的原版特性** - 灵活调整游戏机制以适应不同服务器需求
|
||||
- 📊 **Tpsbar 支持** - 实时显示服务器 TPS 状态
|
||||
- 🐛 **Folia Bug 修复** - 针对 Folia 已知问题的专项修复
|
||||
- 💾 **多存档格式支持** - 支持 linear 和 b_linear(linear 重新实现)存档格式
|
||||
- 🔬 **生电功能增强** - 在 Folia 上实现更多生电内容(完整生电请使用 Fabric)
|
||||
- 🛠️ **更多实用功能** - 持续添加有用的服务器功能
|
||||
|
||||
[English](./README_EN.md) | **中文**
|
||||
## 📥 下载
|
||||
|
||||
## 特性
|
||||
### 稳定版本
|
||||
所有发布版本都可以在 [Releases](https://github.com/LuminolMC/Lophine/releases) 页面找到。
|
||||
|
||||
- 支持部分Bukkit插件
|
||||
- 可配置的原版特性
|
||||
- Tpsbar 支持
|
||||
- 对单线程区域性能的优化
|
||||
- 更多有用的功能
|
||||
### 开发版本
|
||||
如果您想体验最新功能,可以通过以下步骤自行构建。
|
||||
|
||||
## 下载
|
||||
### 构建步骤
|
||||
|
||||
任何版本都可以在 [Release](https://github.com/LuminolMC/Lophine/releases), 中找到,你也可以通过[以下步骤](./README.md#构建)自己构建。
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://github.com/LuminolMC/Lophine.git
|
||||
cd Lophine
|
||||
|
||||
## 构建
|
||||
|
||||
要构建一个paperclip jar,你需要运行以下命令。你可以在lophine-server/build/libs中找到jar(注意:需要`JDK21`)
|
||||
|
||||
```shell
|
||||
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
|
||||
# 应用补丁并构建 Paperclip JAR
|
||||
./gradlew applyAllPatches && ./gradlew createPaperclipJar
|
||||
```
|
||||
|
||||
## 使用API
|
||||
构建完成后,您可以在 `lophine-server/build/libs` 目录中找到生成的 JAR 文件。
|
||||
|
||||
使用 Gradle:
|
||||
## 🔌 API 使用
|
||||
|
||||
### Gradle 配置
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
maven {
|
||||
url = "https://repo.menthamc.com/repository/maven-public/"
|
||||
url = "https://repo.bacteriawa.com/repository/maven-public/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
使用 Maven
|
||||
### Maven 配置
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>menthamc</id>
|
||||
<url>https://repo.menthamc.com/repository/maven-public/</url>
|
||||
<id>repository</id>
|
||||
<url>https://repo.bacteriawa.com/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
## 联系方式
|
||||
## 💬 社区与支持
|
||||
|
||||
> 如果您对这个项目感兴趣或有任何问题,请随时向我们提问。
|
||||
|
||||
**QQ群: [1015048616](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=QML5kIVsniPi1PlZvnjHQT_02EHsZ5Jc&authKey=%2FTCJsZC7JFQ9sxAroPCKuYnlV57Z5fyqp36ewXZk3Sn4iJ9p4MB1JKdc%2FFcX3HOM&noverify=0&group_code=1015048616)** | QQ频道: [点击加入](https://pd.qq.com/s/eq9krf9j) | Telegram: [点击加入](https://t.me/LuminolMinecraft) | Discord: [点击加入](https://discord.gg/Qd7m3V6eDx)
|
||||
### 加入我们的社区
|
||||
|
||||
- **QQ群**: [1015048616](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=QML5kIVsniPi1PlZvnjHQT_02EHsZ5Jc&authKey=%2FTCJsZC7JFQ9sxAroPCKuYnlV57Z5fyqp36ewXZk3Sn4iJ9p4MB1JKdc%2FFcX3HOM&noverify=0&group_code=1015048616)
|
||||
- **QQ频道**: [点击加入](https://pd.qq.com/s/eq9krf9j)
|
||||
- **Telegram**: [点击加入](https://t.me/LuminolMinecraft)
|
||||
- **Discord**: [点击加入](https://discord.gg/Qd7m3V6eDx)
|
||||
|
||||
## 关于 Issue
|
||||
### 获取帮助
|
||||
|
||||
当您遇到任何问题时,请向我们提问,我们将尽力解决,但请记得清楚地描述您的问题并提供足够的日志等信息。
|
||||
- 📋 [提交 Issue](https://github.com/LuminolMC/Lophine/issues)
|
||||
- 💬 [GitHub Discussions](https://github.com/LuminolMC/Lophine/discussions)
|
||||
- 📖 [项目文档](./docs/)
|
||||
|
||||
## 贡献代码
|
||||
## 🐛 问题反馈
|
||||
|
||||
可查看 [Contributing](./docs/CONTRIBUTING.md)
|
||||
当您遇到任何问题时,请向我们提问,我们将尽力解决。请记得:
|
||||
|
||||
## BStats
|
||||
- 📝 **清楚描述问题** - 详细说明问题的具体表现
|
||||
- 📋 **提供完整日志** - 包含错误日志和相关配置信息
|
||||
- 🔍 **环境信息** - 说明服务器版本、插件列表等环境详情
|
||||
- 🔄 **复现步骤** - 如果可能,请提供问题复现的具体步骤
|
||||
|
||||
## 🤝 贡献代码
|
||||
|
||||
我们欢迎社区贡献!详细的贡献指南请查看:
|
||||
|
||||
- 📖 [贡献指南 (中文)](./docs/CONTRIBUTING.md)
|
||||
- 📖 [Contributing Guide (English)](./docs/CONTRIBUTING_EN.md)
|
||||
|
||||
## 📊 项目统计
|
||||
|
||||
### BStats 数据
|
||||
|
||||

|
||||
|
||||
## 特别感谢
|
||||
## 🎉 特别感谢
|
||||
|
||||
<b>感谢[LegacyLands](https://github.com/LegacyLands)对本项目的赞助,如果你想开发一些跨folia/非folia平台的插件,[legacy-lands-library](https://github.com/LegacyLands/legacy-lands-library/)将会是个不错的lib</b>
|
||||
### 项目赞助商
|
||||
|
||||

|
||||
<div align="center">
|
||||
<b>感谢 <a href="https://github.com/LegacyLands">LegacyLands</a> 对本项目的赞助</b>
|
||||
<br>
|
||||
<i>如果你想开发跨 Folia/非 Folia 平台的插件,<a href="https://github.com/LegacyLands/legacy-lands-library/">legacy-lands-library</a> 将会是个不错的选择</i>
|
||||
<br><br>
|
||||
<img src="public/image/legacy-lands-logo.png" alt="LegacyLands Logo" width="200">
|
||||
</div>
|
||||
|
||||
## 请给我们一个 ⭐Star!
|
||||
---
|
||||
|
||||
## ⭐ 请给我们一个 Star!
|
||||
|
||||
> 你的每一个免费的 ⭐Star 就是我们每一个前进的动力。
|
||||
|
||||
### Star 历史
|
||||
|
||||
<a href="https://star-history.com/#LuminolMC/Luminol&LuminolMC/LightingLuminol&LuminolMC/Lophine&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=LuminolMC/Luminol%2CLuminolMC/LightingLuminol%2CLuminolMC/Lophine&type=Date&theme=dark" />
|
||||
@@ -103,3 +151,7 @@ dependencies {
|
||||
<img alt="Star历史表" src="https://api.star-history.com/svg?repos=LuminolMC/Luminol%2CLuminolMC/LightingLuminol%2CLuminolMC/Lophine&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<div align="center">
|
||||
<b>如果这个项目对您有帮助,请不要忘记给我们一个 ⭐Star!</b>
|
||||
</div>
|
||||
+104
-49
@@ -1,98 +1,149 @@
|
||||
<img src="public/image/lophine/lophine3.png" alt="Logo" align="right" width="250">
|
||||
<div align="center">
|
||||
<img src="./public/image/lophine/lophine3.png" alt="Lophine Logo" width="300">
|
||||
|
||||
# Lophine
|
||||
|
||||
*Lophine is a Luminol fork with many useful optimizations and configurable vanilla features, aims to provide more function for survival-usable circuit on folia (Please note that Fabric should be used for complete survival-usable)*
|
||||
|
||||

|
||||
[](LICENSE.md)
|
||||
[](https://github.com/LuminolMC/Lophine/issues)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
**English** | [中文](./README.md)
|
||||
</div>
|
||||
|
||||
# Lophine
|
||||
---
|
||||
|
||||
<h4>Lophine is a Luminol fork with many useful optimizations and configurable vanilla features, aims to provide
|
||||
more function for survival-usable circuit on folia</h4>
|
||||
## ✨ Core Features
|
||||
|
||||
[](LICENSE.md)
|
||||
[](https://github.com/LuminolMC/Lophine/issues)
|
||||

|
||||

|
||||

|
||||
- 🔧 **Configurable Vanilla Features** - Flexibly adjust game mechanics to suit different server needs
|
||||
- 📊 **Tpsbar Support** - Real-time TPS status display
|
||||
- 🐛 **Folia Bug Fixes** - Targeted fixes for known Folia issues
|
||||
- 💾 **Multiple World Format Support** - Support for linear and b_linear (linear reimplementation) world formats
|
||||
- 🔬 **Redstone Enhancement** - More redstone functionality on Folia (use Fabric for complete redstone features)
|
||||
- 🛠️ **More Useful Functions** - Continuously adding useful server features
|
||||
|
||||
**English** | [中文](./README.md)
|
||||
## 📥 Download
|
||||
|
||||
## Features
|
||||
### Stable Releases
|
||||
All release versions can be found on the [Releases](https://github.com/LuminolMC/Lophine/releases) page.
|
||||
|
||||
- Supported some Bukkit plugin
|
||||
- Configurable vanilla features
|
||||
- Tpsbar support
|
||||
- Useful optimizations to improve the performance of single threaded region
|
||||
- More functions
|
||||
### Development Builds
|
||||
If you want to experience the latest features, you can build it yourself following the steps below.
|
||||
|
||||
## Download
|
||||
### Build Steps
|
||||
|
||||
Any versions are available in the [release](https://github.com/LuminolMC/Lophine/releases), also you can build it by yourself through [the following steps](./README_EN.md#Build).
|
||||
```bash
|
||||
# Clone the project
|
||||
git clone https://github.com/LuminolMC/Lophine.git
|
||||
cd Lophine
|
||||
|
||||
## Build
|
||||
|
||||
To build a paperclip jar, you need to run the following command. You can find the jar in lophine-server/build/libs(Note: `JDK21` is needed)
|
||||
|
||||
```shell
|
||||
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
|
||||
# Apply patches and build Paperclip JAR
|
||||
./gradlew applyAllPatches && ./gradlew createPaperclipJar
|
||||
```
|
||||
|
||||
## Using API
|
||||
After building, you can find the generated JAR file in the `lophine-server/build/libs` directory.
|
||||
|
||||
For gradle:
|
||||
## 🔌 API Usage
|
||||
|
||||
### Gradle Configuration
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
maven {
|
||||
url = "https://repo.menthamc.com/repository/maven-public/"
|
||||
url = "https://repo.bacteriawa.com/repository/maven-public/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
||||
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
For maven
|
||||
### Maven Configuration
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>menthamc</id>
|
||||
<url>https://repo.menthamc.com/repository/maven-public/</url>
|
||||
<id>repository</id>
|
||||
<url>https://repo.bacteriawa.com/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.earthme.luminol</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fun.bm.lophine</groupId>
|
||||
<artifactId>luminol-api</artifactId>
|
||||
<version>$VERSION</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
## Contact
|
||||
## 💬 Community & Support
|
||||
|
||||
> If you are interested in this project or have any issue, feel free to ask us.
|
||||
> If you're interested in this project or have any questions, feel free to ask us.
|
||||
|
||||
**QQ Group: [1015048616](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=hTPlI5j6XB8pgk4sdx6RkjhBPGG1r4IR&authKey=pnu6uCKQP7Sja2CJWC15Qi3BeI%2FAsh8tU4m5muufMBjbB3zz%2BwHBZCTRRdSNKhld&noverify=0&group_code=1015048616)** | QQ Channel: [Click To Join](https://pd.qq.com/s/eq9krf9j) | Telegram: [Click To Join](https://t.me/LuminolMinecraft) | Discord: [Click To Join](https://discord.gg/Qd7m3V6eDx)
|
||||
### Join Our Community
|
||||
|
||||
## About Issue
|
||||
- **QQ Group**: [1015048616](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=QML5kIVsniPi1PlZvnjHQT_02EHsZ5Jc&authKey=%2FTCJsZC7JFQ9sxAroPCKuYnlV57Z5fyqp36ewXZk3Sn4iJ9p4MB1JKdc%2FFcX3HOM&noverify=0&group_code=1015048616)
|
||||
- **QQ Channel**: [Join Here](https://pd.qq.com/s/eq9krf9j)
|
||||
- **Telegram**: [Join Here](https://t.me/LuminolMinecraft)
|
||||
- **Discord**: [Join Here](https://discord.gg/Qd7m3V6eDx)
|
||||
|
||||
When you meet any problems, just ask us, we will do our best to solve it, but remember to state your problem clear and provide enough logs etc.</br>
|
||||
### Get Help
|
||||
|
||||
## Pull Requests
|
||||
- 📋 [Submit Issues](https://github.com/LuminolMC/Lophine/issues)
|
||||
- 💬 [GitHub Discussions](https://github.com/LuminolMC/Lophine/discussions)
|
||||
- 📖 [Project Documentation](./docs/)
|
||||
|
||||
See [Contributing](./docs/CONTRIBUTING_EN.md)
|
||||
## 🐛 Bug Reports
|
||||
|
||||
## BStats
|
||||
When you encounter any issues, please ask us and we'll do our best to resolve them. Please remember to:
|
||||
|
||||
- 📝 **Describe the problem clearly** - Provide detailed information about the specific issue
|
||||
- 📋 **Provide complete logs** - Include error logs and relevant configuration information
|
||||
- 🔍 **Environment details** - Specify server version, plugin list, and other environment details
|
||||
- 🔄 **Reproduction steps** - If possible, provide specific steps to reproduce the issue
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome community contributions! For detailed contribution guidelines, please see:
|
||||
|
||||
- 📖 [Contributing Guide (English)](./docs/CONTRIBUTING_EN.md)
|
||||
- 📖 [贡献指南 (中文)](./docs/CONTRIBUTING.md)
|
||||
|
||||
## 📊 Project Statistics
|
||||
|
||||
### BStats Data
|
||||
|
||||

|
||||
|
||||
## Special Thanks
|
||||
## 🎉 Special Thanks
|
||||
|
||||
Thanks [LegacyLands](https://github.com/LegacyLands) for sponsoring this project.If you want to develop some crossing folia/non-folia platform plugins, [legacy-lands-library](https://github.com/LegacyLands/legacy-lands-library/) will be a nice choice for you
|
||||
### Project Sponsors
|
||||
|
||||

|
||||
<div align="center">
|
||||
<b>Thanks to <a href="https://github.com/LegacyLands">LegacyLands</a> for sponsoring this project</b>
|
||||
<br>
|
||||
<i>If you want to develop cross-Folia/non-Folia platform plugins, <a href="https://github.com/LegacyLands/legacy-lands-library/">legacy-lands-library</a> would be a great choice</i>
|
||||
<br><br>
|
||||
<img src="public/image/legacy-lands-logo.png" alt="LegacyLands Logo" width="200">
|
||||
</div>
|
||||
|
||||
## Please ⭐star us!
|
||||
---
|
||||
|
||||
## ⭐ Give Us a Star!
|
||||
|
||||
> Every free ⭐Star you give is the motivation for our every step forward.
|
||||
|
||||
### Star History
|
||||
|
||||
<a href="https://star-history.com/#LuminolMC/Luminol&LuminolMC/LightingLuminol&LuminolMC/Lophine&Date">
|
||||
<picture>
|
||||
@@ -101,3 +152,7 @@ Thanks [LegacyLands](https://github.com/LegacyLands) for sponsoring this project
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=LuminolMC/Luminol%2CLuminolMC/LightingLuminol%2CLuminolMC/Lophine&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<div align="center">
|
||||
<b>If this project helps you, please don't forget to give us a ⭐Star!</b>
|
||||
</div>
|
||||
+11
-8
@@ -3,14 +3,17 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
|
||||
|
||||
plugins {
|
||||
java // TODO java launcher tasks
|
||||
id("moe.luminolmc.hyacinthusweight.patcher") version "+" // Automatically pulls the latest
|
||||
id("moe.luminolmc.hyacinthusweight.patcher")
|
||||
}
|
||||
|
||||
paperweight {
|
||||
filterPatches = false
|
||||
upstreams.register("luminol") {
|
||||
repo = github("LuminolMC", "Luminol")
|
||||
ref = providers.gradleProperty("luminolRef")
|
||||
|
||||
println("Upstream commit ref: " + ref.get())
|
||||
|
||||
patchFile {
|
||||
path = "luminol-server/build.gradle.kts"
|
||||
outputFile = file("lophine-server/build.gradle.kts")
|
||||
@@ -41,7 +44,7 @@ paperweight {
|
||||
}
|
||||
|
||||
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||
val menthaMavenPublicUrl = "https://repo.menthamc.com/repository/maven-public/";
|
||||
val bacteriawaMavenPublicUrl = "https://repo.bacteriawa.com/repository/maven-public/";
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "java-library")
|
||||
@@ -49,14 +52,14 @@ subprojects {
|
||||
|
||||
extensions.configure<JavaPluginExtension> {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
languageVersion = JavaLanguageVersion.of(25)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven(paperMavenPublicUrl)
|
||||
maven(menthaMavenPublicUrl)
|
||||
maven(bacteriawaMavenPublicUrl)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -69,7 +72,7 @@ subprojects {
|
||||
}
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release = 21
|
||||
options.release = 25
|
||||
options.isFork = true
|
||||
}
|
||||
tasks.withType<Javadoc>().configureEach {
|
||||
@@ -88,8 +91,8 @@ subprojects {
|
||||
|
||||
extensions.configure<PublishingExtension> {
|
||||
repositories {
|
||||
maven("https://repo.menthamc.com/repository/maven-snapshots/") {
|
||||
name = "MenthaMC"
|
||||
maven("https://repo.bacteriawa.com/repository/maven-releases/") {
|
||||
name = "Bacteriawa"
|
||||
credentials(PasswordCredentials::class) {
|
||||
username = System.getenv("PRIVATE_MAVEN_REPO_USERNAME")
|
||||
password = System.getenv("PRIVATE_MAVEN_REPO_PASSWORD")
|
||||
@@ -106,4 +109,4 @@ subprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
### Carpet 原版
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `language` | 已映射 | 转发到 `lophine.function.language.lang` |
|
||||
| `commandTick` | 已映射 | 转发到现有的 tick 指令补丁 |
|
||||
| `creativeNoClip` | 已映射 | 转发到 Lophine 的创造飞行穿墙实现 |
|
||||
| `ctrlQCraftingFix` | 结构等价 | 当前的合成与切石机菜单已经自带修复后的 Ctrl+Q 结果槽丢弃行为 |
|
||||
| `placementRotationFix` | 已移植 | 放置朝向判断可使用玩家身体朝向而不是头部旋转 |
|
||||
| `tntDoNotUpdate` | 已移植 | 新放置的 TNT 不会再因放置时更新而自动点燃 |
|
||||
| `explosionNoBlockDamage` | 已移植 | 爆炸仍会伤害实体,但不会破坏方块 |
|
||||
| `interactionUpdates` | 已移植 | 玩家交互和破坏方块时可以在不触发邻居更新与形状更新的情况下运行 |
|
||||
| `xpNoCooldown` | 已移植 | 经验球可以在同一 tick 内被连续吸收,不再有拾取冷却 |
|
||||
| `viewDistance` | 已移植 | 专用服务器启动视距会被兼容配置覆盖 |
|
||||
| `fastRedstoneDust` | 已移植 | 规则启用时,红石粉更新会统一走 Alternate Current 快速更新后端 |
|
||||
| `lagFreeSpawning` | 已移植 | 自然生成会使用轻量碰撞检查与预构造实体路径 |
|
||||
| `defaultLoggers` | 已移植 | 按 Carpet 默认订阅语义为玩家启用 HUD logger,当前支持 `tps`、`mobcaps`、`counter` |
|
||||
| `commandPlayer` | 已映射 | 当前由同一套 `/bot` 假人能力承接 |
|
||||
| `hopperCounters` | 已映射 | 转发到 Lophine 的羊毛漏斗计数器 |
|
||||
|
||||
### Carpet TIS Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `yeetUpdateSuppressionCrash` | 已映射 | 转发到同一套 Lophine 崩溃修复逻辑 |
|
||||
| `dustTrapdoorReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.redstone-ignore-upwards-update` |
|
||||
| `shulkerBoxCCEReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.cce-update-suppression` |
|
||||
| `instantBlockUpdaterReintroduced` | 已映射 | 转发到 `lophine.experiment.redstone.instant-block-updater` |
|
||||
| `optimizedDragonRespawn` | 已映射 | 转发到 Luminol 的末影龙重生优化 |
|
||||
| `antiSpamDisabled` | 已移植 | 在 `ServerGamePacketListenerImpl` 中关闭聊天和创造丢物防刷屏限制 |
|
||||
| `blockPlacementIgnoreEntity` | 已移植 | 创造模式放置方块时忽略实体碰撞检查 |
|
||||
| `creativeOpenContainerForcibly` | 已移植 | 创造玩家可以强制打开被阻挡的箱子、末影箱和潜影盒 |
|
||||
| `observerNoDetection` | 已移植 | 观察者的检测触发会在发出脉冲前被取消 |
|
||||
| `creativeNoItemCooldown` | 已移植 | 创造玩家不会应用物品冷却 |
|
||||
| `totallyNoBlockUpdate` | 已移植 | 邻居更新和形状更新会在 `NeighborUpdater` 中被统一短路 |
|
||||
| `tiscmNetworkProtocol` | 已移植 | 原生 `tiscm:network/v1` 握手与数据包协商已经通过专用 Leaves 协议接入 |
|
||||
| `optimizedTNTHighPriority` | 结构等价 | 当前 `ServerExplosion` 路径已经运行在优化过的服务端爆炸实现上 |
|
||||
| `tntIgnoreRedstoneSignal` | 已移植 | TNT 在自动点燃判断时忽略红石信号 |
|
||||
| `tntDupingFix` | 已移植 | 活塞复制 TNT 的路径现在由 `PistonBaseBlock` 中的兼容规则直接控制 |
|
||||
| `clientSettingsLostOnRespawnFix` | 已移植 | 玩家上一次的客户端设置会在 `ServerPlayer.restoreFrom` 中恢复 |
|
||||
| `entityInstantDeathRemoval` | 已移植 | 已死亡生物不会再保留原版的 20gt 延迟,而是立即移除 |
|
||||
| `farmlandTrampledDisabled` | 已移植 | 耕地不会再因实体踩踏而变回泥土 |
|
||||
| `yeetOutOfOrderChatKick` | 已移植 | 乱序的签名聊天不会再破坏安全聊天链 |
|
||||
| `tickCommandPermission` | 已移植 | `/tick` 的权限等级可通过兼容配置调整 |
|
||||
| `tickFreezeCommandToggleable` | 已移植 | 已冻结时再次执行 `/tick freeze` 会切换回运行状态 |
|
||||
| `syncServerMsptMetricsData` | 已移植 | 实时 MSPT 样本会通过原生 TISCM 协议通道广播 |
|
||||
| `microTiming` | 结构等价 | 当前 Folia 的区块级性能分析与计时钩子已经提供对应的服务端观测能力 |
|
||||
| `optimizedFastEntityMovement` | 结构等价 | Moonrise/Paper 的快速实体移动碰撞优化已经是基础运行时的一部分 |
|
||||
| `optimizedHardHitBoxEntityCollision` | 结构等价 | Moonrise/Paper 的硬碰撞箱实体碰撞优化已经是基础运行时的一部分 |
|
||||
| `tntFuseDuration` | 已移植 | 可配置的 TNT 引信时长已接入 NMS TNT 逻辑 |
|
||||
| `fakePlayerTicksLikeRealPlayer` | 已映射 | 转发到 Leaves 的假人网络阶段 tick 行为 |
|
||||
| `hopperCountersUnlimitedSpeed` | 已映射 | 转发到不限速计数器模式 |
|
||||
|
||||
### Carpet Org Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `hopperNoItemCost` | 已移植 | 漏斗上方放置羊毛时,可在传输后恢复被推出的物品堆,实现零消耗供给线 |
|
||||
| `simpleInGameCalculator` | 已移植 | 以 `=` 开头的聊天内容会作为简单计算表达式私聊回复 |
|
||||
|
||||
### Carpet AMS Addition
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `amsUpdateSuppressionCrashFix` | 已映射 | 转发到 Lophine 现有的更新抑制崩溃修复 |
|
||||
| `creativeOneHitKill` | 已移植 | 创造玩家可通过 `Player.attack` 瞬间击杀附近符合条件的目标 |
|
||||
| `bambooModelNoOffset` | 已移植 | 竹子和竹笋始终返回零模型偏移 |
|
||||
| `carpetAlwaysSetDefault` | 结构等价 | 兼容配置默认值已经会在 `ConfigsInstance.preLoadConfig` 中被写入 |
|
||||
| `powerfulExpMending` | 已移植 | 经验拾取会修复玩家整个背包内所有受损的经验修补物品 |
|
||||
| `sensibleEnderman` | 已移植 | 末影人仅会在规则开启时拾取南瓜和西瓜 |
|
||||
| `shulkerGolem` | 已移植 | 潜影盒上方放置雕刻南瓜时可以召唤潜影贝 |
|
||||
| `preventEndSpikeRespawn` | 已移植 | 末影龙重生时会跳过黑曜石柱重建和柱顶水晶重建 |
|
||||
| `betterCraftableBoneBlock` | 已移植 | 向配方管理器注入 AMS 的替代骨块配方 |
|
||||
| `betterCraftableDispenser` | 已移植 | 向配方管理器注入 AMS 的替代发射器配方 |
|
||||
| `fakePlayerDefaultSurvivalMode` | 已移植 | 新创建的假人可以被强制设为生存模式,而不是沿用服务器默认游戏模式 |
|
||||
| `fakePlayerInteractLikeClient` | 已移植 | 假人与盔甲架交互时会先按真实客户端方式回退,再进入普通实体交互 |
|
||||
| `fakePlayerAutoReplenishmentFormShulkerBox` | 已移植 | 假人自动补货现在可以从背包里的潜影盒中抽取匹配物品 |
|
||||
|
||||
### Lophine 扩展承接
|
||||
|
||||
| 规则 | 状态 | 说明 |
|
||||
| --- | --- |----------------------------------|
|
||||
| `commandBot` | 已映射 | 启用 Lophine `/bot` |
|
||||
| `fakePlayerResident` | 已映射 | 转发到 Lophine 的假人常驻模式 |
|
||||
| `openFakePlayerInventory` | 已映射 | 转发到 Lophine 的假人背包打开功能 |
|
||||
| `fakePlayerAutoReplaceTool` | 已映射 | 为现有自动换工具逻辑增加了新开关 |
|
||||
| `fakePlayerAutoReplenishment` | 已映射 | 为现有自动补货逻辑增加了新开关 |
|
||||
| `fakePlayerReloadAction` | 已映射 | 为假人动作持久化增加了新开关 |
|
||||
| `fakePlayerAutoFish` | 已移植 | 手持鱼竿的假人会自动抛竿和收杆,除非显式执行 `fish` 动作 |
|
||||
+10
-5
@@ -1,10 +1,15 @@
|
||||
group=fun.bm.lophine
|
||||
version=1.21.8-R0.1-SNAPSHOT
|
||||
mcVersion=1.21.8
|
||||
release=2
|
||||
# 0 for skip release, 1 for pre-release, 2 for release
|
||||
mcVersion=26.1.2
|
||||
apiVersion=26.1.2
|
||||
channel=STABLE
|
||||
clipVersion=3.0.18
|
||||
weightVersion=2.0.15
|
||||
# true for release, false for skip release, pre for pre-release
|
||||
release=true
|
||||
# true for push to repo, false for skip push repo, auto for detect by release value
|
||||
pushRepo=auto
|
||||
|
||||
luminolRef=31b05a36d905ef9ffeacf236af8566935c63d83b
|
||||
luminolRef=b796645fdaae7d6b3d3c84fd79f9c090a6458a48
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/luminol-api/build.gradle.kts
|
||||
+++ b/luminol-api/build.gradle.kts
|
||||
@@ -103,20 +_,24 @@
|
||||
@@ -104,20 +_,24 @@
|
||||
srcDir(generatedDir)
|
||||
srcDir(file("../paper-api/src/main/java"))
|
||||
srcDir(file("../folia-api/src/main/java"))
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 11 May 2026 10:47:42 +0800
|
||||
Subject: [PATCH] Add cancel task by task id in FoliaGlobalRegionScheduler
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
index 57455aca80ecc458b96b44c086cea94ddcecae47..763d27d303b9a588526445c453e07f5886534e82 100644
|
||||
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/GlobalRegionScheduler.java
|
||||
@@ -55,4 +55,10 @@ public interface GlobalRegionScheduler {
|
||||
* @param plugin Specified plugin.
|
||||
*/
|
||||
void cancelTasks(@NotNull Plugin plugin);
|
||||
+
|
||||
+ /**
|
||||
+ * Attempts to cancel the specified task.
|
||||
+ * @param taskId The task id.
|
||||
+ */
|
||||
+ void cancelTask(final int taskId);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
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] 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 8e96326c55510642df01ef15e1a3edb1e81176cb..592a3c59bf5edbc65c7c0472e2382593b7b22086 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -3048,4 +3048,15 @@ public final class Bukkit {
|
||||
return server.getFeatureManager();
|
||||
}
|
||||
// Leaves end - Feature API
|
||||
+
|
||||
+ // Leaves start - Bot API
|
||||
+ /**
|
||||
+ * Returns a bot manager.
|
||||
+ *
|
||||
+ * @return Bot Manager
|
||||
+ */
|
||||
+ public static @NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager() {
|
||||
+ return server.getBotManager();
|
||||
+ }
|
||||
+ // Leaves end - Bot API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 473b0e02c003d5317ef798c320e5c845124f4e12..978e015e91408503b4ec84ec5b3c5193255ba7db 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2813,4 +2813,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
double @Nullable [] getRegionTPS(@NotNull World world, int chunkX, int chunkZ);
|
||||
// Folia end - region TPS API
|
||||
+
|
||||
+ // Leaves start - Bot API
|
||||
+ /**
|
||||
+ * Returns a bot manager.
|
||||
+ *
|
||||
+ * @return Bot Manager
|
||||
+ */
|
||||
+ @NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager();
|
||||
+ // Leaves end - Bot API
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 16 Nov 2025 15:50:28 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||
index 592a3c59bf5edbc65c7c0472e2382593b7b22086..838ad878528267b57b69d2938aee0eb6326948eb 100644
|
||||
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||
@@ -3059,4 +3059,10 @@ public final class Bukkit {
|
||||
return server.getBotManager();
|
||||
}
|
||||
// Leaves end - Bot API
|
||||
+
|
||||
+ // Leaves start - Photographer API
|
||||
+ public static @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager() {
|
||||
+ return server.getPhotographerManager();
|
||||
+ }
|
||||
+ // Leaves end - Photographer API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
|
||||
index 978e015e91408503b4ec84ec5b3c5193255ba7db..d054926f6082bba7d0b59e610e5d725ff5f9ffa4 100644
|
||||
--- a/src/main/java/org/bukkit/Server.java
|
||||
+++ b/src/main/java/org/bukkit/Server.java
|
||||
@@ -2822,4 +2822,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||
*/
|
||||
@NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager();
|
||||
// Leaves end - Bot API
|
||||
+
|
||||
+ // Leaves start - Photographer API
|
||||
+ @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager();
|
||||
+ // Leaves end - Photographer API
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.bot;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.action.BotAction;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a fakeplayer
|
||||
*/
|
||||
public interface Bot extends Player {
|
||||
|
||||
/**
|
||||
* Gets the fakeplayer skin
|
||||
*
|
||||
* @return fakeplayer skin name
|
||||
*/
|
||||
@Nullable String getSkinName();
|
||||
|
||||
/**
|
||||
* Gets the fakeplayer name without prefix and suffix
|
||||
*
|
||||
* @return fakeplayer raw name
|
||||
*/
|
||||
@NotNull String getRawName();
|
||||
|
||||
/**
|
||||
* Gets the creator's UUID of the fakeplayer
|
||||
*
|
||||
* @return creator's UUID
|
||||
*/
|
||||
@Nullable UUID getCreatePlayerUUID();
|
||||
|
||||
/**
|
||||
* Add an action to the fakeplayer
|
||||
*
|
||||
* @param action bot action
|
||||
*/
|
||||
<T extends BotAction<T>> void addAction(@NotNull T action);
|
||||
|
||||
/**
|
||||
* Get the copy action in giving index
|
||||
*
|
||||
* @param index index of actions
|
||||
* @return Action of that index
|
||||
*/
|
||||
BotAction<?> getAction(int index);
|
||||
|
||||
/**
|
||||
* Get action size
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
int getActionSize();
|
||||
|
||||
/**
|
||||
* Stop the action in giving index
|
||||
*
|
||||
* @param index index of actions
|
||||
*/
|
||||
void stopAction(int index);
|
||||
|
||||
/**
|
||||
* Stop all the actions of the fakeplayer
|
||||
*/
|
||||
void stopAllActions();
|
||||
|
||||
/**
|
||||
* Remove the fakeplayer
|
||||
*
|
||||
* @param save should save
|
||||
* @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);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.bot;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface BotCreator {
|
||||
|
||||
static BotCreator of(String rawName, Location location) {
|
||||
return Bukkit.getBotManager().botCreator(rawName, location);
|
||||
}
|
||||
|
||||
BotCreator name(String name);
|
||||
|
||||
BotCreator skinName(String skinName);
|
||||
|
||||
BotCreator skin(String[] skin);
|
||||
|
||||
/**
|
||||
* Sets the skin of the bot using the Mojang API based on the provided skin name.
|
||||
* <p>
|
||||
* Need Async.
|
||||
*
|
||||
* @return BotCreator
|
||||
*/
|
||||
BotCreator mojangAPISkin();
|
||||
|
||||
BotCreator location(@NotNull Location location);
|
||||
|
||||
BotCreator creator(@Nullable CommandSender creator);
|
||||
|
||||
/**
|
||||
* Create a bot directly
|
||||
*
|
||||
* @return a bot, null spawn fail
|
||||
*/
|
||||
@Nullable Bot spawn();
|
||||
|
||||
/**
|
||||
* Create a bot and apply skin of player names `skinName` from MojangAPI
|
||||
* just like `mojangAPISkin().spawn()`, but async
|
||||
* <p>
|
||||
* you can not get the bot instance instantly because get skin in on async thread
|
||||
*
|
||||
* @param consumer Consumer
|
||||
*/
|
||||
void spawnWithSkin(Consumer<Bot> consumer);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.bot;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.action.BotAction;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Simple fakeplayer manager
|
||||
*/
|
||||
public interface BotManager {
|
||||
|
||||
/**
|
||||
* Gets a fakeplayer object by the given uuid.
|
||||
*
|
||||
* @param uuid the uuid to look up
|
||||
* @return a fakeplayer if one was found, null otherwise
|
||||
*/
|
||||
@Nullable Bot getBot(@NotNull UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets a fakeplayer object by the given name.
|
||||
*
|
||||
* @param name the name to look up
|
||||
* @return a fakeplayer if one was found, null otherwise
|
||||
*/
|
||||
@Nullable Bot getBot(@NotNull String name);
|
||||
|
||||
/**
|
||||
* Gets a view of all currently logged in fakeplayers. This view is a reused object, making some operations like Collection.size() zero-allocation.
|
||||
*
|
||||
* @return a view of fakeplayers.
|
||||
*/
|
||||
Collection<Bot> getBots();
|
||||
|
||||
/**
|
||||
* Create a bot action by class.
|
||||
*
|
||||
* @param type action class
|
||||
* @return a bot action instance if one was found, null otherwise
|
||||
*/
|
||||
<T extends BotAction<T>> T newAction(@NotNull Class<T> type);
|
||||
|
||||
BotCreator botCreator(@NotNull String rawName, @NotNull Location location);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to attack entities.
|
||||
*/
|
||||
public interface AttackAction extends TimerBotAction<AttackAction> {
|
||||
static AttackAction create() {
|
||||
return Bukkit.getBotManager().newAction(AttackAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Represents an action that can be performed by a Bot.
|
||||
* <p>
|
||||
* This interface defines the basic properties of an action (such as name and UUID)
|
||||
* and lifecycle event callbacks (success, failure, stop).
|
||||
*
|
||||
* @param <T> the type of the callback parameter, usually a context object related to the action
|
||||
*/
|
||||
public interface BotAction<T> {
|
||||
|
||||
/**
|
||||
* Gets the name of this action.
|
||||
*
|
||||
* @return the action name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the UUID of this action.
|
||||
*
|
||||
* @return the UUID of the action
|
||||
*/
|
||||
UUID getUUID();
|
||||
|
||||
/**
|
||||
* Sets whether this action is cancelled.
|
||||
*
|
||||
* @param cancel true to cancel the action, false otherwise
|
||||
*/
|
||||
void setCancelled(boolean cancel);
|
||||
|
||||
/**
|
||||
* Checks whether this action has been cancelled.
|
||||
*
|
||||
* @return true if cancelled, false otherwise
|
||||
*/
|
||||
boolean isCancelled();
|
||||
|
||||
/**
|
||||
* Sets the callback to be executed when the action fails.
|
||||
*
|
||||
* @param onFail the callback to execute on failure, with a parameter of type T
|
||||
*/
|
||||
void setOnFail(Consumer<T> onFail);
|
||||
|
||||
/**
|
||||
* Gets the callback to be executed when the action fails.
|
||||
*
|
||||
* @return the failure callback
|
||||
*/
|
||||
Consumer<T> getOnFail();
|
||||
|
||||
/**
|
||||
* Sets the callback to be executed when the action succeeds.
|
||||
*
|
||||
* @param onSuccess the callback to execute on success, with a parameter of type T
|
||||
*/
|
||||
void setOnSuccess(Consumer<T> onSuccess);
|
||||
|
||||
/**
|
||||
* Gets the callback to be executed when the action succeeds.
|
||||
*
|
||||
* @return the success callback
|
||||
*/
|
||||
Consumer<T> getOnSuccess();
|
||||
|
||||
/**
|
||||
* Sets the callback to be executed when the action is stopped.
|
||||
*
|
||||
* @param onStop the callback to execute on stop, with a parameter of type T
|
||||
*/
|
||||
void setOnStop(Consumer<T> onStop);
|
||||
|
||||
/**
|
||||
* Gets the callback to be executed when the action is stopped.
|
||||
*
|
||||
* @return the stop callback
|
||||
*/
|
||||
Consumer<T> getOnStop();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to break a block.
|
||||
*/
|
||||
public interface BreakBlockAction extends TimerBotAction<BreakBlockAction> {
|
||||
static BreakBlockAction create() {
|
||||
return Bukkit.getBotManager().newAction(BreakBlockAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to drop all items in its inventory.
|
||||
*/
|
||||
public interface DropAction extends TimerBotAction<DropAction> {
|
||||
static DropAction create() {
|
||||
return Bukkit.getBotManager().newAction(DropAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to perform auto fishing.
|
||||
*/
|
||||
public interface FishAction extends TimerBotAction<FishAction> {
|
||||
static FishAction create() {
|
||||
return Bukkit.getBotManager().newAction(FishAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to perform a jump.
|
||||
*/
|
||||
public interface JumpAction extends TimerBotAction<JumpAction> {
|
||||
static JumpAction create() {
|
||||
return Bukkit.getBotManager().newAction(JumpAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to look at a specific position or player.
|
||||
* <p>
|
||||
* If both a position and a player are set, the player target takes precedence.
|
||||
*/
|
||||
public interface LookAction extends BotAction<LookAction> {
|
||||
|
||||
/**
|
||||
* Sets the position in the world for the bot to look at.
|
||||
* <p>
|
||||
* If a player target is set via {@link #setTarget(Player)}, the bot will look at the player instead of this position.
|
||||
*
|
||||
* @param pos the {@link Vector} representing the position to look at
|
||||
* @return this {@code LookAction} instance for method chaining
|
||||
*/
|
||||
LookAction setPos(Vector pos);
|
||||
|
||||
/**
|
||||
* Gets the position in the world that the bot is set to look at.
|
||||
* <p>
|
||||
* If a player target is set, this value may be ignored.
|
||||
*
|
||||
* @return the {@link Vector} position to look at, or {@code null} if not set
|
||||
*/
|
||||
Vector getPos();
|
||||
|
||||
/**
|
||||
* Sets the player for the bot to look at.
|
||||
* <p>
|
||||
* When a player is set as the target, the bot will continuously look at the player's current position,
|
||||
* overriding any position set by {@link #setPos(Vector)}.
|
||||
*
|
||||
* @param player the {@link Player} to look at, or {@code null} to clear the target
|
||||
* @return this {@code LookAction} instance for method chaining
|
||||
*/
|
||||
LookAction setTarget(Player player);
|
||||
|
||||
/**
|
||||
* Gets the player that the bot is set to look at.
|
||||
*
|
||||
* @return the {@link Player} target, or {@code null} if not set
|
||||
*/
|
||||
Player getTarget();
|
||||
|
||||
static LookAction create() {
|
||||
return Bukkit.getBotManager().newAction(LookAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to mount to nearby vehicles.
|
||||
*/
|
||||
public interface MountAction extends BotAction<MountAction> {
|
||||
static MountAction create() {
|
||||
return Bukkit.getBotManager().newAction(MountAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to move to a specific direction.
|
||||
*/
|
||||
public interface MoveAction extends StateBotAction<MoveAction> {
|
||||
|
||||
/**
|
||||
* Gets the direction of the move action.
|
||||
*
|
||||
* @return the direction of the move action
|
||||
*/
|
||||
MoveDirection getDirection();
|
||||
|
||||
/**
|
||||
* Sets the direction of the move action.
|
||||
*
|
||||
* @param direction the direction to set
|
||||
* @return this action instance
|
||||
*/
|
||||
MoveAction setDirection(MoveDirection direction);
|
||||
|
||||
/**
|
||||
* Represents possible movement directions for the bot.
|
||||
*/
|
||||
enum MoveDirection {
|
||||
FORWARD("forward"),
|
||||
BACKWARD("backward"),
|
||||
LEFT("left"),
|
||||
RIGHT("right");
|
||||
|
||||
public final String name;
|
||||
|
||||
MoveDirection(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
static MoveAction create() {
|
||||
return Bukkit.getBotManager().newAction(MoveAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to rotate to a specific yaw and pitch.
|
||||
*/
|
||||
public interface RotationAction extends BotAction<RotationAction> {
|
||||
|
||||
/**
|
||||
* Sets the yaw of the rotation.
|
||||
*
|
||||
* @param yaw the yaw to set
|
||||
* @return this action instance
|
||||
*/
|
||||
RotationAction setYaw(float yaw);
|
||||
|
||||
/**
|
||||
* Sets the pitch of the rotation.
|
||||
*
|
||||
* @param pitch the pitch to set
|
||||
* @return this action instance
|
||||
*/
|
||||
RotationAction setPitch(float pitch);
|
||||
|
||||
/**
|
||||
* Gets the yaw of the rotation.
|
||||
*
|
||||
* @return the yaw
|
||||
*/
|
||||
float getYaw();
|
||||
|
||||
/**
|
||||
* Gets the pitch of the rotation.
|
||||
*
|
||||
* @return the pitch
|
||||
*/
|
||||
float getPitch();
|
||||
|
||||
static RotationAction create() {
|
||||
return Bukkit.getBotManager().newAction(RotationAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to sneak.
|
||||
*/
|
||||
public interface SneakAction extends StateBotAction<SneakAction> {
|
||||
static SneakAction create() {
|
||||
return Bukkit.getBotManager().newAction(SneakAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
/**
|
||||
* Represents a type of bot action that places the bot in a specific state while the action is active.
|
||||
* When the action is stopped, the associated state is removed from the bot.
|
||||
*
|
||||
* @param <E> The type of entity that this action operates on.
|
||||
*/
|
||||
public interface StateBotAction<E> extends BotAction<E> {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to swap items between the main hand and off-hand.
|
||||
*/
|
||||
public interface SwapAction extends BotAction<SwapAction> {
|
||||
static SwapAction create() {
|
||||
return Bukkit.getBotManager().newAction(SwapAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action for a bot to float up in water.
|
||||
*/
|
||||
public interface SwimAction extends StateBotAction<SwimAction> {
|
||||
static SwimAction create() {
|
||||
return Bukkit.getBotManager().newAction(SwimAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
/**
|
||||
* Represents a scheduled bot task that runs periodically.
|
||||
* <p>
|
||||
* TimerBotAction allows configuration of start delay, execution interval, and the number of executions.
|
||||
* It is intended for bot actions that need to be triggered at regular intervals.
|
||||
*
|
||||
* @param <E> the type of entity this action operates on
|
||||
*/
|
||||
public interface TimerBotAction<E> extends BotAction<E> {
|
||||
|
||||
/**
|
||||
* Sets the delay in ticks before the task starts for the first time.
|
||||
*
|
||||
* @param delayTick the number of ticks to delay before the first execution
|
||||
*/
|
||||
void setStartDelayTick(int delayTick);
|
||||
|
||||
/**
|
||||
* Gets the delay in ticks before the task starts for the first time.
|
||||
*
|
||||
* @return the number of ticks to delay before the first execution
|
||||
*/
|
||||
int getStartDelayTick();
|
||||
|
||||
/**
|
||||
* Sets the interval in ticks between each execution of the task.
|
||||
*
|
||||
* @param intervalTick the number of ticks between executions
|
||||
*/
|
||||
void setDoIntervalTick(int intervalTick);
|
||||
|
||||
/**
|
||||
* Gets the interval in ticks between each execution of the task.
|
||||
*
|
||||
* @return the number of ticks between executions
|
||||
*/
|
||||
int getDoIntervalTick();
|
||||
|
||||
/**
|
||||
* Sets the total number of times the task should be executed.
|
||||
*
|
||||
* @param doNumber the total number of executions
|
||||
*/
|
||||
void setDoNumber(int doNumber);
|
||||
|
||||
/**
|
||||
* Gets the total number of times the task should be executed.
|
||||
*
|
||||
* @return the total number of executions
|
||||
*/
|
||||
int getDoNumber();
|
||||
|
||||
/**
|
||||
* Gets the number of ticks remaining until the next execution.
|
||||
*
|
||||
* @return the number of ticks until the next execution
|
||||
*/
|
||||
int getTickToNext();
|
||||
|
||||
/**
|
||||
* Gets the number of executions remaining for this task.
|
||||
*
|
||||
* @return the number of executions remaining
|
||||
*/
|
||||
int getDoNumberRemaining();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot only uses an item, without using it on blocks or entities.
|
||||
*/
|
||||
public interface UseItemAction extends TimerBotAction<UseItemAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemAction.class);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot uses an item, fully simulating the effect of a player right-clicking.
|
||||
*/
|
||||
public interface UseItemAutoAction extends TimerBotAction<UseItemAutoAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemAutoAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemAutoAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemAutoAction.class);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot only uses the item in its offhand, without using it on blocks or entities.
|
||||
*/
|
||||
public interface UseItemOffhandAction extends TimerBotAction<UseItemOffhandAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemOffhandAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemOffhandAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemOffhandAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot uses an item on a block.
|
||||
*/
|
||||
public interface UseItemOnAction extends TimerBotAction<UseItemOnAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemOnAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemOnAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemOnAction.class);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot uses an item in its offhand on a block.
|
||||
*/
|
||||
public interface UseItemOnOffhandAction extends TimerBotAction<UseItemOnOffhandAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemOnOffhandAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemOnOffhandAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemOnOffhandAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot uses an item to an entity.
|
||||
*/
|
||||
public interface UseItemToAction extends TimerBotAction<UseItemToAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemToAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemToAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemToAction.class);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.bot.action;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Represents an action where a bot uses an item in its offhand to an entity.
|
||||
*/
|
||||
public interface UseItemToOffhandAction extends TimerBotAction<UseItemToOffhandAction> {
|
||||
|
||||
/**
|
||||
* Gets the equivalent right-click hold duration timeout in ticks.
|
||||
* Default is -1, which means no timeout.
|
||||
*
|
||||
* @return the equivalent right-click hold duration timeout
|
||||
*/
|
||||
int getUseTickTimeout();
|
||||
|
||||
/**
|
||||
* Sets the equivalent right-click hold duration timeout in ticks.
|
||||
*
|
||||
* @param timeout the equivalent right-click hold duration timeout
|
||||
* @return this action instance
|
||||
*/
|
||||
UseItemToOffhandAction setUseTickTimeout(int timeout);
|
||||
|
||||
static UseItemToOffhandAction create() {
|
||||
return Bukkit.getBotManager().newAction(UseItemToOffhandAction.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.entity.photographer;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface Photographer extends Player {
|
||||
|
||||
@NotNull String getId();
|
||||
|
||||
void setRecordFile(@NotNull File file);
|
||||
|
||||
void stopRecording();
|
||||
|
||||
void stopRecording(boolean async);
|
||||
|
||||
void stopRecording(boolean async, boolean save);
|
||||
|
||||
void pauseRecording();
|
||||
|
||||
void resumeRecording();
|
||||
|
||||
void setFollowPlayer(@Nullable Player player);
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.entity.photographer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.replay.BukkitRecorderOption;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface PhotographerManager {
|
||||
@Nullable Photographer getPhotographer(@NotNull UUID uuid);
|
||||
|
||||
@Nullable Photographer getPhotographer(@NotNull String id);
|
||||
|
||||
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location);
|
||||
|
||||
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption);
|
||||
|
||||
void removePhotographer(@NotNull String id);
|
||||
|
||||
void removePhotographer(@NotNull UUID uuid);
|
||||
|
||||
void removeAllPhotographers();
|
||||
|
||||
Collection<Photographer> getPhotographers();
|
||||
}
|
||||
@@ -0,0 +1,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.event.bot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class BotActionEvent extends BotEvent {
|
||||
|
||||
private final String actionName;
|
||||
private final UUID actionUUID;
|
||||
|
||||
public BotActionEvent(@NotNull Bot who, String actionName, UUID actionUUID) {
|
||||
super(who);
|
||||
this.actionName = actionName;
|
||||
this.actionUUID = actionUUID;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getActionName() {
|
||||
return actionName;
|
||||
}
|
||||
|
||||
public UUID getActionUUID() {
|
||||
return actionUUID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BotActionExecuteEvent extends BotActionEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private Result result = Result.PASS;
|
||||
|
||||
public BotActionExecuteEvent(@NotNull Bot who, String actionName, UUID actionUUID) {
|
||||
super(who, actionName, actionUUID);
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return result != Result.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.result = cancel ? Result.SOFT_CANCEL : Result.PASS;
|
||||
}
|
||||
|
||||
public void hardCancel() {
|
||||
this.result = Result.HARD_CANCEL;
|
||||
}
|
||||
|
||||
public Result getResult() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public enum Result {
|
||||
PASS, SOFT_CANCEL, HARD_CANCEL
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BotActionScheduleEvent extends BotActionEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final CommandSender sender;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotActionScheduleEvent(@NotNull Bot who, String actionName, UUID actionUUID, CommandSender sender) {
|
||||
super(who, actionName, actionUUID);
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BotActionStopEvent extends BotActionEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final CommandSender sender;
|
||||
private final Reason reason;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotActionStopEvent(@NotNull Bot who, String actionName, UUID actionUUID, Reason stopReason, CommandSender sender) {
|
||||
super(who, actionName, actionUUID);
|
||||
this.reason = stopReason;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public enum Reason {
|
||||
DONE, COMMAND, PLUGIN, INTERNAL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
public class BotConfigModifyEvent extends BotEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final String configName;
|
||||
private final String[] configValue;
|
||||
private final CommandSender sender;
|
||||
private boolean cancel;
|
||||
|
||||
public BotConfigModifyEvent(@NotNull Bot who, String configName, String[] configValue, CommandSender sender) {
|
||||
super(who);
|
||||
this.configName = configName;
|
||||
this.configValue = configValue;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getConfigName() {
|
||||
return configName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String[] getConfigValue() {
|
||||
return configValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Call when a fakeplayer created
|
||||
*/
|
||||
public class BotCreateEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final String bot;
|
||||
private final String skin;
|
||||
private final CreateReason reason;
|
||||
private final CommandSender creator;
|
||||
private Location createLocation;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotCreateEvent(@NotNull final String who, @NotNull final String skin, @NotNull final Location createLocation, @NotNull CreateReason reason, @Nullable CommandSender creator) {
|
||||
this.bot = who;
|
||||
this.skin = skin;
|
||||
this.createLocation = createLocation;
|
||||
this.reason = reason;
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fakeplayer name
|
||||
*
|
||||
* @return fakeplayer name
|
||||
*/
|
||||
public String getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location to create the fakeplayer
|
||||
*
|
||||
* @return Location to create the fakeplayer
|
||||
*/
|
||||
@NotNull
|
||||
public Location getCreateLocation() {
|
||||
return createLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location to create the fakeplayer
|
||||
*
|
||||
* @param createLocation location to create the fakeplayer
|
||||
*/
|
||||
public void setCreateLocation(@NotNull Location createLocation) {
|
||||
this.createLocation = createLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fakeplayer skin
|
||||
*
|
||||
* @return fakeplayer skin name
|
||||
*/
|
||||
@Nullable
|
||||
public String getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the create reason of the bot
|
||||
*
|
||||
* @return create reason
|
||||
*/
|
||||
@NotNull
|
||||
public CreateReason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the creator of the bot
|
||||
* if the create reason is not COMMAND, the creator might be null
|
||||
*
|
||||
* @return An optional of creator
|
||||
*/
|
||||
@Nullable
|
||||
public CommandSender getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public enum CreateReason {
|
||||
COMMAND,
|
||||
PLUGIN,
|
||||
INTERNAL,
|
||||
UNKNOWN,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
public class BotDeathEvent extends BotEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private boolean cancel = false;
|
||||
private boolean sendDeathMessage;
|
||||
private Component deathMessage;
|
||||
|
||||
public BotDeathEvent(@NotNull Bot who, @Nullable Component deathMessage, boolean sendDeathMessage) {
|
||||
super(who);
|
||||
this.deathMessage = deathMessage;
|
||||
this.sendDeathMessage = sendDeathMessage;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public Component deathMessage() {
|
||||
return deathMessage;
|
||||
}
|
||||
|
||||
public void deathMessage(Component deathMessage) {
|
||||
this.deathMessage = deathMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDeathMessage() {
|
||||
return this.deathMessage == null ? null : LegacyComponentSerializer.legacySection().serialize(this.deathMessage);
|
||||
}
|
||||
|
||||
public void setDeathMessage(@Nullable String deathMessage) {
|
||||
this.deathMessage = deathMessage != null ? LegacyComponentSerializer.legacySection().deserialize(deathMessage) : null;
|
||||
}
|
||||
|
||||
public boolean isSendDeathMessage() {
|
||||
return sendDeathMessage;
|
||||
}
|
||||
|
||||
public void setSendDeathMessage(boolean sendDeathMessage) {
|
||||
this.sendDeathMessage = sendDeathMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
/**
|
||||
* Represents a fakeplayer related event
|
||||
*/
|
||||
public abstract class BotEvent extends Event {
|
||||
|
||||
protected Bot bot;
|
||||
|
||||
public BotEvent(@NotNull final Bot who) {
|
||||
bot = who;
|
||||
}
|
||||
|
||||
public BotEvent(@NotNull final Bot who, boolean async) {
|
||||
super(async);
|
||||
bot = who;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fakeplayer involved in this event
|
||||
*
|
||||
* @return Fakeplayer who is involved in this event
|
||||
*/
|
||||
@NotNull
|
||||
public final Bot getBot() {
|
||||
return bot;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
public class BotInventoryOpenEvent extends BotEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Player player;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotInventoryOpenEvent(@NotNull Bot who, @Nullable Player player) {
|
||||
super(who);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player getOpenPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
/**
|
||||
* Called when a fakeplayer joins a server
|
||||
*/
|
||||
public class BotJoinEvent extends BotEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Component joinMessage;
|
||||
|
||||
public BotJoinEvent(@NotNull final Bot who, @Nullable final Component joinMessage) {
|
||||
super(who);
|
||||
this.joinMessage = joinMessage;
|
||||
}
|
||||
|
||||
public BotJoinEvent(@NotNull final Bot who, @Nullable final String joinMessage) {
|
||||
super(who);
|
||||
this.joinMessage = joinMessage != null ? LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public void joinMessage(@Nullable final Component joinMessage) {
|
||||
this.joinMessage = joinMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Component joinMessage() {
|
||||
return joinMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the join message to send to all online players
|
||||
*
|
||||
* @return string join message. Can be null
|
||||
*/
|
||||
@Nullable
|
||||
public String getJoinMessage() {
|
||||
return this.joinMessage == null ? null : LegacyComponentSerializer.legacySection().serialize(this.joinMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the join message to send to all online players
|
||||
*
|
||||
* @param joinMessage join message. If null, no message will be sent
|
||||
*/
|
||||
public void setJoinMessage(@Nullable String joinMessage) {
|
||||
this.joinMessage = joinMessage != null ? LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Call when a fakeplayer loaded
|
||||
*/
|
||||
public class BotLoadEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final String bot;
|
||||
private final UUID botUUID;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotLoadEvent(@NotNull final String who, @NotNull final UUID uuid) {
|
||||
this.bot = who;
|
||||
this.botUUID = uuid;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fakeplayer name
|
||||
*
|
||||
* @return fakeplayer name
|
||||
*/
|
||||
public String getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public UUID getBotUUID() {
|
||||
return botUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
/**
|
||||
* Call when a fakeplayer removed
|
||||
*/
|
||||
public class BotRemoveEvent extends BotEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final RemoveReason reason;
|
||||
private final CommandSender remover;
|
||||
private Component removeMessage;
|
||||
private boolean save;
|
||||
private boolean cancel = false;
|
||||
|
||||
public BotRemoveEvent(@NotNull final Bot who, @NotNull RemoveReason reason, @Nullable CommandSender remover, @Nullable Component removeMessage, boolean save) {
|
||||
super(who);
|
||||
this.reason = reason;
|
||||
this.remover = remover;
|
||||
this.removeMessage = removeMessage;
|
||||
this.save = save;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remove reason of the bot
|
||||
*
|
||||
* @return remove reason
|
||||
*/
|
||||
@NotNull
|
||||
public RemoveReason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remover of the bot
|
||||
* if the remove reason is not COMMAND, the creator might be null
|
||||
*
|
||||
* @return An optional of remover
|
||||
*/
|
||||
@Nullable
|
||||
public CommandSender getRemover() {
|
||||
return remover;
|
||||
}
|
||||
|
||||
public Component removeMessage() {
|
||||
return removeMessage;
|
||||
}
|
||||
|
||||
public void removeMessage(Component removeMessage) {
|
||||
this.removeMessage = removeMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getRemoveMessage() {
|
||||
return this.removeMessage == null ? null : LegacyComponentSerializer.legacySection().serialize(this.removeMessage);
|
||||
}
|
||||
|
||||
public void setRemoveMessage(@Nullable String removeMessage) {
|
||||
this.removeMessage = removeMessage != null ? LegacyComponentSerializer.legacySection().deserialize(removeMessage) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
public boolean shouldSave() {
|
||||
return save;
|
||||
}
|
||||
|
||||
public void setSave(boolean save) {
|
||||
this.save = save;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public enum RemoveReason {
|
||||
COMMAND,
|
||||
PLUGIN,
|
||||
DEATH,
|
||||
INTERNAL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.event.bot;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.leavesmc.leaves.entity.bot.Bot;
|
||||
|
||||
public class BotSpawnLocationEvent extends BotEvent {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Location spawnLocation;
|
||||
|
||||
public BotSpawnLocationEvent(@NotNull final Bot who, @NotNull Location spawnLocation) {
|
||||
super(who);
|
||||
this.spawnLocation = spawnLocation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Location getSpawnLocation() {
|
||||
return spawnLocation;
|
||||
}
|
||||
|
||||
public void setSpawnLocation(@NotNull Location location) {
|
||||
this.spawnLocation = location;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.event.player;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when a player operation is limited
|
||||
*/
|
||||
public class PlayerOperationLimitEvent extends PlayerEvent {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Block block;
|
||||
private final Operation operation;
|
||||
|
||||
public PlayerOperationLimitEvent(@NotNull Player who, Operation operation, Block block) {
|
||||
super(who);
|
||||
this.block = block;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the operated block
|
||||
*
|
||||
* @return block
|
||||
*/
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of operation
|
||||
*
|
||||
* @return operation type
|
||||
*/
|
||||
public Operation getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public enum Operation {
|
||||
MINE, PLACE
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.event.player;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class UpdateSuppressionEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final @Nullable Player player;
|
||||
private final @Nullable Location position;
|
||||
private final @Nullable Material material;
|
||||
private final @NotNull Throwable throwable;
|
||||
|
||||
public UpdateSuppressionEvent(@Nullable Player player, @Nullable Location position, @Nullable Material material, @NotNull Throwable throwable) {
|
||||
this.player = player;
|
||||
this.position = position;
|
||||
this.material = material;
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public @Nullable Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public @NotNull Throwable getThrowable() {
|
||||
return throwable;
|
||||
}
|
||||
|
||||
public @Nullable Location getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public @Nullable Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.replay;
|
||||
|
||||
public class BukkitRecorderOption {
|
||||
|
||||
// public int recordDistance = -1;
|
||||
public String serverName = "Lophine"; // Lophine - rebrand to Lophine to avoid confusion
|
||||
public BukkitRecordWeather forceWeather = BukkitRecordWeather.NULL;
|
||||
public int forceDayTime = -1;
|
||||
public boolean ignoreChat = false;
|
||||
// public boolean ignoreItem = false;
|
||||
|
||||
public enum BukkitRecordWeather {
|
||||
CLEAR,
|
||||
RAIN,
|
||||
THUNDER,
|
||||
NULL
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/luminol-server/build.gradle.kts
|
||||
+++ b/luminol-server/build.gradle.kts
|
||||
@@ -52,7 +_,23 @@
|
||||
@@ -50,7 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
+ activeFork = lophine
|
||||
|
||||
|
||||
spigot {
|
||||
@@ -142,12 +_,16 @@
|
||||
|
||||
@@ -125,12 +_,16 @@
|
||||
resources { srcDir("../paper-server/src/main/resources") }
|
||||
java { srcDir("../folia-server/src/main/java") }
|
||||
resources { srcDir("../folia-server/src/main/resources") }
|
||||
@@ -42,40 +42,31 @@
|
||||
}
|
||||
}
|
||||
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
||||
@@ -174,7 +_,7 @@
|
||||
@@ -158,7 +_,7 @@
|
||||
}
|
||||
|
||||
dependencies {
|
||||
- implementation(project(":luminol-api")) // Luminol
|
||||
+ implementation(project(":lophine-api")) // Lophine
|
||||
- implementation(project(":luminol-api"))
|
||||
+ implementation(project(":lophine-api"))
|
||||
// Luminol start - Dependenices insert
|
||||
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
|
||||
implementation("com.github.luben:zstd-jni:1.5.4-1")
|
||||
@@ -276,14 +_,14 @@
|
||||
implementation("net.objecthunter:exp4j:0.4.8")
|
||||
implementation("com.electronwill.night-config:toml:3.9.0") // Night config
|
||||
@@ -234,14 +_,14 @@
|
||||
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
|
||||
attributes(
|
||||
"Main-Class" to "org.bukkit.craftbukkit.Main",
|
||||
- "Implementation-Title" to "Luminol",
|
||||
+ "Implementation-Title" to "Lophine",
|
||||
- "Implementation-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Implementation-Title" to "Lophine", // Luminol - Rebrand
|
||||
"Implementation-Version" to implementationVersion,
|
||||
"Implementation-Vendor" to date,
|
||||
- "Specification-Title" to "Luminol",
|
||||
+ "Specification-Title" to "Lophine",
|
||||
- "Specification-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Specification-Title" to "Lophine", // Luminol - Rebrand
|
||||
"Specification-Version" to project.version,
|
||||
"Specification-Vendor" to "LuminolMC org",
|
||||
- "Brand-Id" to "luminolmc:luminol",
|
||||
- "Brand-Name" to "Luminol",
|
||||
+ "Brand-Id" to "luminolmc:lophine",
|
||||
+ "Brand-Name" to "Lophine",
|
||||
"Specification-Vendor" to "LuminoLMC", // Luminol - Rebrand
|
||||
- "Brand-Id" to "luminolmc:luminol", // Luminol - Rebrand
|
||||
- "Brand-Name" to "Luminol", // Luminol - Rebrand
|
||||
+ "Brand-Id" to "luminolmc:lophine", // Luminol - Rebrand
|
||||
+ "Brand-Name" to "Lophine", // Luminol - Rebrand
|
||||
"Build-Number" to (build ?: ""),
|
||||
"Build-Time" to buildTime.toString(),
|
||||
"Git-Branch" to gitBranch,
|
||||
@@ -447,7 +_,7 @@
|
||||
}
|
||||
|
||||
fill {
|
||||
- project("luminol")
|
||||
+ project("lophine")
|
||||
versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") })
|
||||
version(paperweight.minecraftVersion)
|
||||
|
||||
|
||||
@@ -5,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 0a3fa2756dae0eea9e2c0fa6bbaa425584763036..6c1cb2866c81a1bc861289aedb2c318f910a8498 100644
|
||||
index 3b700b214ac6818cd75c34b207aa1436f52231e7..315c137cb9dbac51a8ac0d63f0ae0127e57c6c9f 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -19,6 +19,7 @@ public class ConfigManager {
|
||||
@@ -25,6 +25,7 @@ public class ConfigManager {
|
||||
|
||||
public static void initConfigs() throws IOException {
|
||||
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
|
||||
public static void initConfigs() {
|
||||
registerConfig("luminol", builder.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
+ registerConfig("lophine", builder.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
|
||||
preLoad();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
|
||||
index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 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
|
||||
@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
|
||||
@@ -8,7 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "server_mod_name")
|
||||
public class ServerModNameConfig implements IConfigModule {
|
||||
@ConfigInfo(baseName = "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(baseName = "vanilla_spoof")
|
||||
@ConfigInfo(name = "vanilla_spoof", comments = "Ignore any plugin's modification and server mod name set in this config block, only force sending brand name of vanilla")
|
||||
public static boolean fakeVanilla = false;
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 16 Mar 2026 15:51:40 +0800
|
||||
Subject: [PATCH] Diff in auto-update patch
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
index ce01352b637547c1cf8308d56d4b3f9c48fcca70..9b5623ce1de3d68c949c3c00b966cedab3a4c986 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
@@ -16,13 +16,13 @@ import java.util.Set;
|
||||
category = EnumConfigCategory.MISC,
|
||||
name = "auto_update",
|
||||
comments = """
|
||||
- Checks GitHub Releases for newer Luminol jars on a schedule.
|
||||
- Downloads are staged under auto_update/luminol and written to auto_update/core.path,
|
||||
+ Checks GitHub Releases for newer version's jars on a schedule.
|
||||
+ Downloads are staged under auto_update/lophine and written to auto_update/core.path,
|
||||
which Hyacinthusclip can consume on the next restart.
|
||||
- If target_jar_path is set, Luminol will also try to replace that launcher jar directly."""
|
||||
+ If target_jar_path is set, server will also try to replace that launcher jar directly."""
|
||||
)
|
||||
public class AutoUpdateConfig implements IConfigModule {
|
||||
- @ConfigInfo(name = "enabled", comments = "Whether Luminol should check for updates automatically.")
|
||||
+ @ConfigInfo(name = "enabled", comments = "Whether the server should check for updates automatically.")
|
||||
public static boolean enabled = false;
|
||||
|
||||
@ConfigInfo(name = "check_times", comments = "List of daily check times in HH:mm, based on the server's local time zone.")
|
||||
@@ -33,7 +33,7 @@ public class AutoUpdateConfig implements IConfigModule {
|
||||
|
||||
@ConfigInfo(name = "target_jar_path", comments = """
|
||||
Optional launcher jar path to replace after a successful download.
|
||||
- Leave this blank to keep the downloaded jar staged in auto_update/luminol
|
||||
+ Leave this blank to keep the downloaded jar staged in auto_update/lophine
|
||||
and let Hyacinthusclip switch to it through auto_update/core.path on restart.""")
|
||||
public static String targetJarPath = "";
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
index 94a25cd681c9352d6931edafd9ec67fd7ba8a777..d0d0cf5e5ff8d4b8efa4d9778c27267b41cf8cf8 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
@@ -35,10 +35,10 @@ public final class AutoUpdateHelper {
|
||||
private final Logger LOGGER = LogUtils.getClassLogger();
|
||||
private final Gson GSON = new Gson();
|
||||
|
||||
- private final String GITHUB_API_BASE = "https://api.github.com/repos/LuminolMC/Luminol";
|
||||
+ private final String GITHUB_API_BASE = "https://api.github.com/repos/lophineMC/lophine";
|
||||
private final Path AUTO_UPDATE_DIR = Path.of("auto_update");
|
||||
private final Path CORE_PATH_FILE = AUTO_UPDATE_DIR.resolve("core.path");
|
||||
- private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("luminol");
|
||||
+ private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("lophine");
|
||||
private final Path LATEST_PATH_FILE = LUMINOL_UPDATE_DIR.resolve("latest.path");
|
||||
private final long DAILY_TASK_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
@@ -51,13 +51,13 @@ public final class AutoUpdateHelper {
|
||||
ensureWorkingDirectories();
|
||||
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor(task -> {
|
||||
- final Thread thread = new Thread(task, "Luminol Auto Update Scheduler");
|
||||
+ final Thread thread = new Thread(task, "Lophine Auto Update Scheduler");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
if (AutoUpdateConfig.checkTimes.isEmpty()) {
|
||||
- LOGGER.warn("Luminol auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
+ LOGGER.warn("Lophine auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,14 +95,14 @@ public final class AutoUpdateHelper {
|
||||
|
||||
private void checkForUpdatesSafely() {
|
||||
if (!UPDATE_RUNNING.compareAndSet(false, true)) {
|
||||
- LOGGER.info("A Luminol auto-update check is already running, skipping this schedule.");
|
||||
+ LOGGER.info("A Lophine auto-update check is already running, skipping this schedule.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
checkForUpdates();
|
||||
} catch (Exception e) {
|
||||
- LOGGER.warn("Luminol auto-update failed.", e);
|
||||
+ LOGGER.warn("Lophine auto-update failed.", e);
|
||||
} finally {
|
||||
UPDATE_RUNNING.set(false);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final ReleaseAssetInfo latestRelease = getLatestCompatibleRelease(mcVersion, gitBranch);
|
||||
if (latestRelease == null) {
|
||||
- LOGGER.warn("No compatible Luminol release was found for Minecraft {}{}.",
|
||||
+ LOGGER.warn("No compatible Lophine release was found for Minecraft {}{}.",
|
||||
mcVersion,
|
||||
gitBranch == null ? "" : " on branch " + gitBranch
|
||||
);
|
||||
@@ -132,7 +132,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final UpdateStatus updateStatus = compareReleaseWithCurrentBuild(latestRelease.releaseCommitHash(), currentGitHash);
|
||||
if (updateStatus == UpdateStatus.UP_TO_DATE) {
|
||||
- LOGGER.info("You are already running the latest compatible Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("You are already running the latest compatible Lophine release: {}", latestRelease.tagName());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public final class AutoUpdateHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
- LOGGER.info("Found a newer Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("Found a newer Lophine release: {}", latestRelease.tagName());
|
||||
|
||||
final Path stagedJar = downloadAndStageRelease(latestRelease);
|
||||
final Path finalJarPath = tryApplyTargetJar(stagedJar);
|
||||
@@ -163,7 +163,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
if (finalJarPath.equals(stagedJar)) {
|
||||
LOGGER.info(
|
||||
- "Downloaded the latest Luminol jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
+ "Downloaded the latest Lophine jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
finalJarPath.toAbsolutePath()
|
||||
);
|
||||
} else {
|
||||
@@ -179,7 +179,7 @@ public final class AutoUpdateHelper {
|
||||
try {
|
||||
Files.createDirectories(LUMINOL_UPDATE_DIR);
|
||||
} catch (IOException e) {
|
||||
- throw new RuntimeException("Failed to create Luminol auto update directory", e);
|
||||
+ throw new RuntimeException("Failed to create Lophine auto update directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ public final class AutoUpdateHelper {
|
||||
private @NotNull HttpURLConnection openConnection(String url) throws IOException, URISyntaxException {
|
||||
final HttpURLConnection connection = (HttpURLConnection) new URI(url).toURL().openConnection();
|
||||
connection.setRequestProperty("Accept", "application/vnd.github+json");
|
||||
- connection.setRequestProperty("User-Agent", "Luminol Auto Update");
|
||||
+ connection.setRequestProperty("User-Agent", "Lophine Auto Update");
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(10000);
|
||||
return connection;
|
||||
@@ -1,18 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 28 Jul 2025 23:02:47 +0800
|
||||
Subject: [PATCH] Transformed Configs
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
|
||||
index 531214d7ab28ece4bf84e82b39d1c9f983f0fb0c..b68fa0427bb975e91e76f73ab4cc089a424937a3 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
|
||||
@@ -5,6 +5,7 @@ import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
|
||||
public class CommandBlockExecutionConfig implements IConfigModule {
|
||||
+ @me.earthme.luminol.config.flags.TransformedConfig(name = "command_block_enabled", category = {"experiment", "command"}, originInstance = "lophine")
|
||||
@ConfigInfo(baseName = "enabled")
|
||||
public static boolean enabled = false;
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 13 Aug 2025 22:23:46 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
index a5df7e40369cf2c309f4d37fede6615f34a467e2..84d0e1a7cd687ac4ed9f1bf824ca28940c2fab1e 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
@@ -17,10 +17,98 @@
|
||||
|
||||
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;
|
||||
|
||||
// Only used part of the original code was copied
|
||||
public class ItemOverstackUtils {
|
||||
+
|
||||
+ private static final List<ItemUtil> overstackUtils = List.of(
|
||||
+ new ShulkerBox()
|
||||
+ );
|
||||
+
|
||||
+ public static int getItemStackMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxServerStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static int getNetworkMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxClientStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && util.tryStackItems(self, other)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean hasOverstackingItem() {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static int getItemStackMaxCountReal(ItemStack stack) {
|
||||
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
|
||||
+ return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize());
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ int modifiedMaxStackSize = getNetworkMaxCount(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.putInt("Leaves.RealStackSize", realMaxStackSize);
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != realMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.remove("Leaves.RealStackSize");
|
||||
+ if (nbt.isEmpty()) {
|
||||
+ itemStack.remove(DataComponents.CUSTOM_DATA);
|
||||
+ } else {
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
public static float getItemStackSignalStrength(int maxStackSize, ItemStack itemStack) {
|
||||
float result = (float) itemStack.getCount() / Math.min(maxStackSize, itemStack.getMaxStackSize());
|
||||
/*if (LeavesConfig.modify.oldMC.allowGrindstoneOverstacking && CurseEnchantedBook.isCursedEnchantedBook(itemStack)) { // Luminol
|
||||
@@ -28,4 +116,80 @@ public class ItemOverstackUtils {
|
||||
}*/ // Luminol
|
||||
return Math.clamp(result, 0f, 1f);
|
||||
}
|
||||
+
|
||||
+ public static boolean isStackable(ItemStack itemStack) {
|
||||
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
|
||||
+ }
|
||||
+
|
||||
+ private interface ItemUtil {
|
||||
+ boolean isEnabled();
|
||||
+
|
||||
+ boolean tryStackItems(ItemEntity self, ItemEntity other);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ int getMaxServerStackCount(ItemStack stack);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ default int getMaxClientStackCount(ItemStack stack) {
|
||||
+ return getMaxServerStackCount(stack);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class ShulkerBox implements ItemUtil {
|
||||
+ public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
||||
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
|
||||
+ return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
+ }
|
||||
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
+ }
|
||||
+
|
||||
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
|
||||
+ // Leaves - Paper 26.1: ItemContainerContents#stream() removed, use nonEmptyItemCopyStream()
|
||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).nonEmptyItemCopyStream().findAny().isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEnabled() {
|
||||
+ return ContainerExpansionConfig.shulkerCount > 1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ ItemStack selfStack = self.getItem();
|
||||
+ if (!(selfStack.getItem() instanceof BlockItem blockItem) || !(blockItem.getBlock() instanceof ShulkerBoxBlock)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ ItemStack otherStack = other.getItem();
|
||||
+ if (selfStack.getItem() == otherStack.getItem()
|
||||
+ && shulkerBoxCheck(selfStack, otherStack)
|
||||
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
|
||||
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
|
||||
+
|
||||
+ selfStack.grow(amount);
|
||||
+ self.setItem(selfStack);
|
||||
+
|
||||
+ self.pickupDelay = Math.max(other.pickupDelay, self.pickupDelay);
|
||||
+ self.age = Math.min(other.getAge(), self.age);
|
||||
+
|
||||
+ otherStack.shrink(amount);
|
||||
+ if (otherStack.isEmpty()) {
|
||||
+ other.discard();
|
||||
+ } else {
|
||||
+ other.setItem(otherStack);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxServerStackCount(ItemStack stack) {
|
||||
+ if (stack.getItem() instanceof BlockItem bi &&
|
||||
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
||||
+ return ContainerExpansionConfig.shulkerCount;
|
||||
+ }
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 18 Feb 2026 00:15:08 +0800
|
||||
Subject: [PATCH] Leaves: Fakeplayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
index a4c188f71564fc77a9fa22b4cae032e1919d06f2..019266803f1452cb1e76350da8edae10a77020ac 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
@@ -54,6 +54,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
|
||||
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) {
|
||||
@@ -110,6 +116,11 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
|
||||
this.trackingPlayers.add(player);
|
||||
|
||||
scheduleIfOffTarget(player, () -> {
|
||||
+ // Leaves start - fakeplayer
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
for (WaypointTransmitter transmitter : this.waypoints) {
|
||||
this.createConnection(player, transmitter);
|
||||
}
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab5822601939 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -11,14 +11,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
private final Set<String> availableFeatures = new HashSet<>();
|
||||
|
||||
private ServerFeatureManager() {
|
||||
- if (false) { // Luminol not provide this
|
||||
- availableFeatures.addAll(Set.of(
|
||||
- FAKEPLAYER,
|
||||
- PHOTOGRAPHER,
|
||||
- BYTEBUF,
|
||||
- UPDATE_SUPPRESSION_EVENT
|
||||
- ));
|
||||
- }
|
||||
+ availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 17 May 2026 05:33:21 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -12,6 +12,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
|
||||
private ServerFeatureManager() {
|
||||
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 3 Jun 2026 13:49:39 +0800
|
||||
Subject: [PATCH] Update suppression event
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c..c3db6c5281728fa1a2b4d84f9ebff9fcfd696698 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -13,6 +13,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
private ServerFeatureManager() {
|
||||
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
|
||||
+ availableFeatures.add(UPDATE_SUPPRESSION_EVENT); // Lophine - update suppression event support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sun, 22 Mar 2026 01:39:17 +0800
|
||||
Subject: [PATCH] Carpet features
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index 315c137cb9dbac51a8ac0d63f0ae0127e57c6c9f..2a2d6aff636ad960638b357d224a631c89d23d33 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -26,6 +26,15 @@ public class ConfigManager {
|
||||
public static void initConfigs() {
|
||||
registerConfig("luminol", builder.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
registerConfig("lophine", builder.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
|
||||
+ // Lophine start - add carpet config
|
||||
+ registerConfig("lophine_carpet", builder.of(
|
||||
+ new java.io.File("lophine_config"),
|
||||
+ "lophine_carpet",
|
||||
+ "lophine_carpet_config.toml",
|
||||
+ "lophinecarpetconfig",
|
||||
+ "fun.bm.lophine.carpet.config.modules"
|
||||
+ ));
|
||||
+ // Lophine end - add carpet config
|
||||
preLoad();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 5 Jun 2026 16:10:25 +0800
|
||||
Subject: [PATCH] Carpet Features Compatible
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
index f079a1cd99d648dc7ca97fb65406b7a42ad5a74e..30f78cbae7aea3e9fcee6d97f229ddf8e8344299 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
@@ -23,9 +23,4 @@ public class CommandConfig implements IConfigModule {
|
||||
""")
|
||||
@HotReloadUnsupported
|
||||
public static boolean waypointsAndWaypointCommand = false;
|
||||
- @ConfigInfo(name = "enable_tick_command", comments = """
|
||||
- Only freeze/unfreeze/step/query command is allowed if you enabled it.
|
||||
- WARN: This should disabled in production environment!
|
||||
- """)
|
||||
- public static boolean tick = false;
|
||||
}
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
|
||||
deleted file mode 100644
|
||||
index f791feed92abd750ac10775c05150f122ecbe886..0000000000000000000000000000000000000000
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
|
||||
+++ /dev/null
|
||||
@@ -1,12 +0,0 @@
|
||||
-package me.earthme.luminol.config.modules.optimizations;
|
||||
-
|
||||
-import me.earthme.luminol.config.IConfigModule;
|
||||
-import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
-import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
-import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
-
|
||||
-@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "end_dragon")
|
||||
-public class OptimizedDragonRespawnConfig implements IConfigModule {
|
||||
- @ConfigInfo(name = "optimized_dragon_respawn")
|
||||
- public static boolean optimizedRespawn = false;
|
||||
-}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 15 Jun 2026 01:33:32 +0800
|
||||
Subject: [PATCH] TEMP: Temporarily transform config between different config
|
||||
system
|
||||
|
||||
Should be removed in Minecraft 26.2 Update
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index 2a2d6aff636ad960638b357d224a631c89d23d33..536e8d7df4ce9de1dbe587c1af6b2474a530a165 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -65,6 +65,12 @@ public class ConfigManager {
|
||||
CompletableFuture.allOf(futures).join();
|
||||
CommandRegister.register(); // register command after config loaded to enable some command didn't depend on config files
|
||||
initialized = true;
|
||||
+
|
||||
+ // Lophine start - temporarily transform configs
|
||||
+ reApplyStagedConfigs();
|
||||
+ saveConfigs();
|
||||
+ configfiles.values().forEach((config) -> config.reload(true, false));
|
||||
+ // Lophine end - temporarily transform configs
|
||||
}
|
||||
|
||||
public static void registerRunnableBeforeFinalLoad(Runnable runnable) {
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 21 May 2025 13:04:00 +0800
|
||||
Subject: [PATCH] Add config to disable end crystal check
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..3f1520bdd5ef708824712ea62974fedb35067f23 100644
|
||||
--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
+++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
@@ -547,6 +547,8 @@ public class EndDragonFight {
|
||||
|
||||
blockPos = this.portalLocation;
|
||||
}
|
||||
+ // Luminol start - Disable end crystal check
|
||||
+ if (!fun.bm.lophine.config.modules.fixes.DisableEndCrystalCheckConfig.disableCheck) {
|
||||
// Paper start - Perf: Do crystal-portal proximity check before entity lookup
|
||||
if (placedEndCrystalPos != null) {
|
||||
// The end crystal must be 0 or 1 higher than the portal origin
|
||||
@@ -562,6 +564,7 @@ public class EndDragonFight {
|
||||
}
|
||||
}
|
||||
// Paper end - Perf: Do crystal-portal proximity check before entity lookup
|
||||
+ } // Luminol end - Disable end crystal check
|
||||
|
||||
|
||||
List<EndCrystal> list = Lists.newArrayList();
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 12 Jun 2025 04:44:24 +0800
|
||||
Subject: [PATCH] Server I18n
|
||||
|
||||
|
||||
diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java
|
||||
index 49c7f8194be8222e329fc3215a6aa6db0b221b11..c6c968d28e0d14a4c50e66bdd5176a000944b707 100644
|
||||
--- a/net/minecraft/locale/Language.java
|
||||
+++ b/net/minecraft/locale/Language.java
|
||||
@@ -37,6 +37,7 @@ public abstract class Language {
|
||||
Map<String, String> loadedData = new HashMap<>();
|
||||
BiConsumer<String, String> output = loadedData::put;
|
||||
parseTranslations(output, "/assets/minecraft/lang/en_us.json");
|
||||
+ fun.bm.lophine.utils.ServerI18nUtil.loadLophineI18nDefault(output); // Lophine - Server I18n
|
||||
deprecatedInfo.applyToMap(loadedData);
|
||||
final Map<String, String> storage = Map.copyOf(loadedData);
|
||||
return new Language() {
|
||||
@@ -66,7 +67,7 @@ public abstract class Language {
|
||||
};
|
||||
}
|
||||
|
||||
- private static void parseTranslations(final BiConsumer<String, String> output, final String path) {
|
||||
+ public static void parseTranslations(final BiConsumer<String, String> output, final String path) { // Lophine - private -> public
|
||||
try (InputStream stream = Language.class.getResourceAsStream(path)) {
|
||||
loadFromJson(stream, output);
|
||||
} catch (JsonParseException | IOException var7) {
|
||||
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
|
||||
index 143ad4e342b184aa02b6fbbe81508e244eebc7a2..89be42b8519522398920eb424c894fd2ab8c9666 100644
|
||||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -155,6 +155,8 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
|
||||
+ fun.bm.lophine.utils.ServerI18nUtil.preInit(); // Lophine - I18n support
|
||||
+
|
||||
// Paper start - Detect headless JRE
|
||||
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 dfac07850b02abba160f8f143eba4569172ab9e9..fcd4b4785f0d09f87fe214202468c75395157e14 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -283,6 +283,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // Luminol - load config file
|
||||
+ fun.bm.lophine.utils.ServerI18nUtil.init(); // Lophine - I18n support
|
||||
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()) {
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
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
|
||||
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
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -299,6 +299,11 @@ public final class RegionizedServer {
|
||||
this.randomWalk();
|
||||
*/
|
||||
++this.tickCount;
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ MinecraftServer.tickRateManager.tick();
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
// expire invalid click command callbacks
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
@@ -322,6 +327,13 @@ public final class RegionizedServer {
|
||||
this.globalTick(world, tickCount);
|
||||
}
|
||||
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ MinecraftServer.tickRateManager.reduceSprintTicks();
|
||||
+ MinecraftServer.tickRateManager.endTickWork();
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
+
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
@@ -455,7 +467,7 @@ public final class RegionizedServer {
|
||||
}
|
||||
|
||||
private void tickTime(final ServerLevel world, final int 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);
|
||||
}
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index 0357792de0ed8ec9058d1847c8b45c33ff365af6..4945c11f573a53df2f5be4beb7af6a3f4d32f7d4 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -31,8 +31,8 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
- public static final int TICK_RATE = 20;
|
||||
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
|
||||
+ public static float TICK_RATE = 20; // Luminol - Add tick command support
|
||||
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Luminol - Add tick command support
|
||||
|
||||
// Folia start - watchdog
|
||||
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
|
||||
@@ -394,8 +394,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));
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ final int tickCount;
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
|
||||
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
|
||||
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
|
||||
+ tickCount = 1;
|
||||
+ } else {
|
||||
+ TICK_RATE = MinecraftServer.tickRateManager.tickrate();
|
||||
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
|
||||
+ tickCount = Math.max(1, 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));
|
||||
+ }
|
||||
+ // Luminol end - Add tick command support
|
||||
|
||||
if (!this.tryMarkTicking()) {
|
||||
if (!this.cancelled.get()) {
|
||||
@@ -435,6 +450,11 @@ public final class TickRegionScheduler {
|
||||
try {
|
||||
// next start isn't updated until the end of this tick
|
||||
this.tickRegion(tickCount, tickStart, scheduledEnd);
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ MinecraftServer.tickRateManager.endTickWork();
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
} catch (final Throwable thr) {
|
||||
this.scheduler.regionFailed(this, false, thr);
|
||||
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 8a90aa5c145f53afbb3f2371f97cb09974f30bbb..0d5ed9602492c8393088954105e9a19032067b8b 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -243,7 +243,11 @@ public class Commands {
|
||||
TeleportCommand.register(this.dispatcher);
|
||||
TellRawCommand.register(this.dispatcher, context);
|
||||
//TestCommand.register(this.dispatcher, context); // Folia - region threading
|
||||
- //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
|
||||
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
TimeCommand.register(this.dispatcher);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 2ed2f4cca3a81117c0beaf7a11bbbe8156f6a9ce..6675b83c9f15d0341dcf169ec3ac20f401c5d10b 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;
|
||||
public MinecraftServer.ReloadableResources resources;
|
||||
private final StructureTemplateManager structureTemplateManager;
|
||||
- private final ServerTickRateManager tickRateManager;
|
||||
+ public static ServerTickRateManager tickRateManager; // Luminol - Add tick command support
|
||||
protected WorldData worldData;
|
||||
public PotionBrewing potionBrewing;
|
||||
private FuelValues fuelValues;
|
||||
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
|
||||
index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c60d14fd87 100644
|
||||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -105,7 +105,7 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
return false;
|
||||
} else if (this.remainingSprintTicks > 0L) {
|
||||
this.sprintTickStartTime = System.nanoTime();
|
||||
- this.remainingSprintTicks--;
|
||||
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
|
||||
return true;
|
||||
} else {
|
||||
this.finishTickSprint();
|
||||
@@ -113,6 +113,12 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol start - Add tick command support
|
||||
+ public void reduceSprintTicks() {
|
||||
+ this.remainingSprintTicks--;
|
||||
+ }
|
||||
+ // Luminol end - Add tick command support
|
||||
+
|
||||
public void endTickWork() {
|
||||
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
|
||||
index 126685fb266692082b432ed297a499149e921dfb..9d8f6025c420e651611da17e77a362c738228b72 100644
|
||||
--- a/net/minecraft/server/commands/TickCommand.java
|
||||
+++ b/net/minecraft/server/commands/TickCommand.java
|
||||
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
|
||||
import net.minecraft.util.TimeUtil;
|
||||
|
||||
public class TickCommand {
|
||||
- private static final float MAX_TICKRATE = 10000.0F;
|
||||
+ public static final float MAX_TICKRATE = 10000.0F; // Luminol - Add tick command support
|
||||
private static final String DEFAULT_TICKRATE = String.valueOf(20);
|
||||
|
||||
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 2 Jul 2025 23:36:25 +0800
|
||||
Subject: [PATCH] Fix datapack command save function
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index e7eec08a4d8943b35a76173e39529498c348140c..61983a80191e64942bfdac74c6d2f23cf781484d 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2475,6 +2475,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.reloadResources(packsToEnable, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
}
|
||||
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ public void saveDatapacks(Collection<String> selectedPacks) {
|
||||
+ this.packRepository.setSelected(selectedPacks, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
|
||||
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
|
||||
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
|
||||
+ );
|
||||
+ this.worldData.setDataConfiguration(worldDataConfiguration);
|
||||
+ }
|
||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||
+
|
||||
public CompletableFuture<Void> reloadResources(
|
||||
final Collection<String> packsToEnable, final io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause
|
||||
) {
|
||||
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
|
||||
index 0c7c829270d3cd3dd05a3dc7dfe82ee01d5c6bd8..991e0362e96488b64d994f1bdfb8ed5d66f98666 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( // Lophine - Fix datapack command save function
|
||||
Commands.literal("enable")
|
||||
.then(
|
||||
Commands.argument("name", StringArgumentType.string())
|
||||
@@ -145,11 +145,11 @@ public class DataPackCommand {
|
||||
.suggests(SELECTED_PACKS)
|
||||
.executes(c -> disablePack(c.getSource(), getPack(c, "name", false)))
|
||||
)
|
||||
- )*/ // Luminol - Add back read-only datapack command
|
||||
+ )
|
||||
.then(
|
||||
Commands.literal("list")
|
||||
.executes(c -> listPacks(c.getSource()))
|
||||
- //.then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource()))) // Luminol - Add back read-only datapack command
|
||||
+ .then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource()))) // Luminol - Add back read-only datapack command
|
||||
.then(Commands.literal("enabled").executes(c -> listEnabledPacks(c.getSource())))
|
||||
)
|
||||
.then(
|
||||
@@ -235,7 +235,7 @@ public class DataPackCommand {
|
||||
}
|
||||
|
||||
private static int listPacks(final CommandSourceStack source) {
|
||||
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
|
||||
+ return listEnabledPacks(source) + listAvailablePacks(source); // Lophine - Fix datapack command save function
|
||||
}
|
||||
|
||||
private static int listAvailablePacks(final CommandSourceStack source) {
|
||||
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
|
||||
index 80fef4277b9e986c17a4cb895e130726bdb63229..4bed8d0432508cbe5c0d1fc7d68052ec2af7260f 100644
|
||||
--- a/net/minecraft/server/commands/ReloadCommand.java
|
||||
+++ b/net/minecraft/server/commands/ReloadCommand.java
|
||||
@@ -16,11 +16,17 @@ public class ReloadCommand {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static void reloadPacks(final Collection<String> selectedPacks, final CommandSourceStack source) {
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ source.getServer().saveDatapacks(selectedPacks);
|
||||
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
|
||||
+ if (false) {
|
||||
source.getServer().reloadResources(selectedPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
|
||||
LOGGER.warn("Failed to execute reload", throwable);
|
||||
source.sendFailure(Component.translatable("commands.reload.failure"));
|
||||
return null;
|
||||
});
|
||||
+ }
|
||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||
}
|
||||
|
||||
private static Collection<String> discoverNewPacks(final PackRepository packRepository, final WorldData worldData, final Collection<String> currentPacks) {
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 2 Jul 2025 23:36:25 +0800
|
||||
Subject: [PATCH] Add config to enable datapack command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 0d5ed9602492c8393088954105e9a19032067b8b..e2fc15d84fafde6847ecead23c55169449275e1b 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.CommandDataConfig.enabled) {
|
||||
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 86d20d884fb59d0121bdcc291af1fc97b8bf603d..a0f1db50adf5163a671d3d9e9df7adb7de4250c6 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2352,6 +2352,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
}
|
||||
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ public void saveDatapacks(Collection<String> selectedIds) {
|
||||
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
|
||||
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
|
||||
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
|
||||
+ );
|
||||
+ this.worldData.setDataConfiguration(worldDataConfiguration);
|
||||
+ }
|
||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||
+
|
||||
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
|
||||
// Paper end - Add ServerResourcesReloadedEvent
|
||||
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
|
||||
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
|
||||
index b540a3c3a02f7242578a63477e34b9063e86f1d2..9f0adf157872e1c68cd7752a24eacdc636e8d17a 100644
|
||||
--- a/net/minecraft/server/commands/ReloadCommand.java
|
||||
+++ b/net/minecraft/server/commands/ReloadCommand.java
|
||||
@@ -16,6 +16,12 @@ public class ReloadCommand {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
|
||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||
+ if (true) {
|
||||
+ source.getServer().saveDatapacks(selectedIds);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
|
||||
LOGGER.warn("Failed to execute reload", throwable);
|
||||
source.sendFailure(Component.translatable("commands.reload.failure"));
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 20 Feb 2025 01:00:28 +0800
|
||||
Subject: [PATCH] Purpur: Barrels and enderchests 6 rows
|
||||
|
||||
Co-authored by: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/dc46f46d28dcdcaf33bb533f9571a107db98c1d7/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index c9d3b000a328fe3583a7053a94c72dc003c1e10c..45e5ac1e8e2ec30935e96fa20d18e77bbd0e20bd 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -963,6 +963,10 @@ public abstract class PlayerList {
|
||||
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
|
||||
this.server.getCommands().sendCommands(player);
|
||||
} // Paper - Add sendOpLevel API
|
||||
+
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ player.enderChestSlotCount = fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows : 27;
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
// 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 592ce8beb28ebe8aaac2ed167abb24148afb0bc3..ce8ab4b7eee5e0715e780d189d2f6554c5a9dc3c 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -175,6 +175,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
public float hurtDir;
|
||||
public boolean affectsSpawning = true; // Paper - Affects Spawning API
|
||||
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
|
||||
+ public int enderChestSlotCount = -1; // Purpur - Barrels and enderchests 6 rows
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
|
||||
index e77bfcd31cdcfd5836dc5db561e3fe2bc552a4b1..297657f38ce4c4bfa58cca27d440595246200d94 100644
|
||||
--- a/net/minecraft/world/inventory/ChestMenu.java
|
||||
+++ b/net/minecraft/world/inventory/ChestMenu.java
|
||||
@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, inventory, 6);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu oneRow(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 1);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu twoRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 2);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu threeRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 3);
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ public static ChestMenu fourRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 4);
|
||||
+ }
|
||||
+
|
||||
+ public static ChestMenu fiveRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
+ return new ChestMenu(MenuType.GENERIC_9x3, containerId, inventory, container, 5);
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public static ChestMenu sixRows(final int containerId, final Inventory inventory, final Container container) {
|
||||
return new ChestMenu(MenuType.GENERIC_9x6, containerId, inventory, container, 6);
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
index 4df3a32faf85595372f4b250482d852c985ea3ab..101b3711bfb98888837ebed323561cac6efb274d 100644
|
||||
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
|
||||
@@ -26,11 +26,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
|
||||
}
|
||||
|
||||
public PlayerEnderChestContainer(Player owner) {
|
||||
- super(27);
|
||||
+ super(fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows : 27);
|
||||
this.owner = owner;
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ @Override
|
||||
+ public int getContainerSize() {
|
||||
+ return owner.enderChestSlotCount < 0 ? super.getContainerSize() : owner.enderChestSlotCount;
|
||||
+ }
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public void setActiveChest(final EnderChestBlockEntity activeChest) {
|
||||
this.activeChest = activeChest;
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
index 24a2c411da0ebbb7f97d621bb76ff686621f9aae..a9f511a549681a76a962855c26b9af5980f36df7 100644
|
||||
--- a/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
@@ -88,7 +88,15 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
// Paper start - Fix InventoryOpenEvent cancellation - moved up;
|
||||
container.setActiveChest(enderChest); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
|
||||
if (level instanceof ServerLevel serverLevel && player.openMenu(
|
||||
- new SimpleMenuProvider((containerId, inventory, p) -> ChestMenu.threeRows(containerId, inventory, container), CONTAINER_TITLE)
|
||||
+ new SimpleMenuProvider(
|
||||
+ (containerId, inventory, p) -> switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.enderchestRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(containerId, inventory, container);
|
||||
+ case 5 -> ChestMenu.fiveRows(containerId, inventory, container);
|
||||
+ case 4 -> ChestMenu.fourRows(containerId, inventory, container);
|
||||
+ case 2 -> ChestMenu.twoRows(containerId, inventory, container);
|
||||
+ case 1 -> ChestMenu.oneRow(containerId, inventory, container);
|
||||
+ default -> ChestMenu.threeRows(containerId, inventory, container);
|
||||
+ }, CONTAINER_TITLE) // Purpur - Barrels and enderchests 6 rows
|
||||
).isPresent()) {
|
||||
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
|
||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
index 61e39a18c0fba22699750e5c0187d19a0433b9a2..98c48426fcbb4aeba479e87ab27b03e17b50d7f5 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
||||
@@ -60,7 +60,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
// CraftBukkit end
|
||||
private static final Component DEFAULT_NAME = Component.translatable("container.barrel");
|
||||
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
|
||||
+ case 6 -> 54;
|
||||
+ case 5 -> 45;
|
||||
+ case 4 -> 36;
|
||||
+ case 2 -> 18;
|
||||
+ case 1 -> 9;
|
||||
+ default -> 27;
|
||||
+ }, ItemStack.EMPTY);
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
+
|
||||
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
||||
{
|
||||
Objects.requireNonNull(BarrelBlockEntity.this);
|
||||
@@ -123,7 +133,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
- return 27;
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ return switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
|
||||
+ case 6 -> 54;
|
||||
+ case 5 -> 45;
|
||||
+ case 4 -> 36;
|
||||
+ case 2 -> 18;
|
||||
+ case 1 -> 9;
|
||||
+ default -> 27;
|
||||
+ };
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,7 +163,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Override
|
||||
protected AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
||||
- return ChestMenu.threeRows(containerId, inventory, this);
|
||||
+ // Purpur start - Barrels and enderchests 6 rows
|
||||
+ return switch (fun.bm.lophine.config.modules.function.ContainerExpansionConfig.barrelRows) {
|
||||
+ case 6 -> ChestMenu.sixRows(containerId, inventory, this);
|
||||
+ case 5 -> ChestMenu.fiveRows(containerId, inventory, this);
|
||||
+ case 4 -> ChestMenu.fourRows(containerId, inventory, this);
|
||||
+ case 2 -> ChestMenu.twoRows(containerId, inventory, this);
|
||||
+ case 1 -> ChestMenu.oneRow(containerId, inventory, this);
|
||||
+ default -> ChestMenu.threeRows(containerId, inventory, this);
|
||||
+ };
|
||||
+ // Purpur end - Barrels and enderchests 6 rows
|
||||
}
|
||||
|
||||
@Override
|
||||
+25
-25
@@ -1,55 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 3 Aug 2025 14:26:37 +0800
|
||||
Subject: [PATCH] Disable some check for operators
|
||||
Subject: [PATCH] Add config to disable some check for operators
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index a684f5edf420d9655046de872c54e0c1a89103cf..105675bef05408bd5baf1b6129c0392065bbe79d 100644
|
||||
index e12927623e8de82a6105b0cb0e6b58a6c45cff7e..0b5f2060062a354bd6cafa8f53a5734dc83d062d 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -367,7 +367,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -399,7 +399,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.tickCount++;
|
||||
this.knownMovePacketCount = this.receivedMovePacketCount;
|
||||
if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) {
|
||||
- if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player)) {
|
||||
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
+ if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingPlayer, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause
|
||||
return;
|
||||
@@ -386,7 +386,7 @@ public class ServerGamePacketListenerImpl
|
||||
return true;
|
||||
@@ -418,7 +418,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.vehicleLastGoodY = this.lastVehicle.getY();
|
||||
this.vehicleLastGoodZ = this.lastVehicle.getZ();
|
||||
if (this.clientVehicleIsFloating && this.lastVehicle.getControllingPassenger() == this.player) {
|
||||
- if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle)) {
|
||||
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && this.player.hasPermissions(2))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
+ if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle) && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpFlyCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable fly check for operator
|
||||
// LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getPlainTextName()); // Paper - Logging moved to net.minecraft.server.network.ServerCommonPacketListenerImpl.disconnect()
|
||||
this.disconnect(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.flyingVehicle, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause
|
||||
return;
|
||||
@@ -644,7 +644,7 @@ public class ServerGamePacketListenerImpl
|
||||
d5 = d2 - rootVehicle.getZ();
|
||||
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
boolean flag1 = false;
|
||||
- if (!me.earthme.luminol.config.modules.misc.DisableMovedWronglyThreshold.enabled && d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableMovedWronglyThreshold.enabled && d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Spigot // Lophine - disable move check for operator
|
||||
flag1 = true; // Paper - diff on change, this should be moved wrongly
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
|
||||
return true;
|
||||
@@ -671,7 +671,7 @@ public class ServerGamePacketListenerImpl
|
||||
zDist = targetZ - vehicle.getZ();
|
||||
movedDist = xDist * xDist + yDist * yDist + zDist * zDist;
|
||||
boolean fail = false;
|
||||
- if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot // Leaves - disable can
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Spigot // Leaves - disable can // Lophine - disable move check for operator
|
||||
fail = true;
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", vehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(movedDist));
|
||||
}
|
||||
@@ -1540,7 +1540,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1603,7 +1603,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
toX, toY, toZ, toYaw, toPitch, true);
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
- if (!event.isAllowed()) {
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
|
||||
if (event.getLogWarning()) {
|
||||
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5);
|
||||
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), xDist, yDist, zDist);
|
||||
}
|
||||
@@ -1618,7 +1618,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1682,7 +1682,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY,
|
||||
toX, toY, toZ, toYaw, toPitch, true);
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
- if (!event.isAllowed()) {
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && this.player.hasPermissions(2))) { // Lophine - disable move check for operator
|
||||
+ if (!event.isAllowed() && !(fun.bm.lophine.config.modules.misc.DisableCheckConfig.disableOpMoveCheck && MinecraftServer.getServer().getPlayerList().isOp(this.player.nameAndId()))) { // Lophine - disable move check for operator
|
||||
movedWrongly = true;
|
||||
if (event.getLogWarning())
|
||||
// Paper end
|
||||
-207
@@ -1,207 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 11 Apr 2025 16:53:57 +0800
|
||||
Subject: [PATCH] Add config to revert raid changes
|
||||
|
||||
Co-authored by: huanli233 <392352840@qq.com>
|
||||
Some of changes is a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/b5793e809b6346e16b7ea218496806a312562e27/leaves-server/minecraft-patches/features/0106-Revert-raid-changes.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
index 80f17f33f670018240c854df589cf90cdeab6e70..985f27d249810bf133a520d937b7006e57f553ec 100644
|
||||
--- a/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
@@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect {
|
||||
&& !serverPlayer.isSpectator()
|
||||
&& level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& level.isVillage(serverPlayer.blockPosition())) {
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.trigger) {
|
||||
+ return level.getRaids().createOrExtendRaid(serverPlayer, serverPlayer.blockPosition()) == null;
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
Raid raidAt = level.getRaidAt(serverPlayer.blockPosition());
|
||||
if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) {
|
||||
serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier));
|
||||
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
|
||||
index 1910bff3f08147bfd63703097e30b9f88c84e337..26f4d7359f638a11ea2d768d18091e261d6b1791 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -340,7 +340,20 @@ public class Raid {
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
- this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ // Luminol Start - Raid revert
|
||||
+ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
|
||||
+ this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ } else {
|
||||
+ int n4 = 0;
|
||||
+ if (this.raidCooldownTicks < 100) {
|
||||
+ n4 = 1;
|
||||
+ }
|
||||
+ if (this.raidCooldownTicks < 40) {
|
||||
+ n4 = 2;
|
||||
+ }
|
||||
+ this.waveSpawnPos = this.getValidSpawnPos(level, n4);
|
||||
+ }
|
||||
+ // Luminol End - Raid revert
|
||||
}
|
||||
|
||||
if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) {
|
||||
@@ -375,7 +388,14 @@ public class Raid {
|
||||
int i = 0;
|
||||
|
||||
while (this.shouldSpawnGroup()) {
|
||||
- BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ // Luminol Start - Raid revert
|
||||
+ BlockPos blockPos;
|
||||
+ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
|
||||
+ blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ } else {
|
||||
+ blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(level, i, 20);
|
||||
+ }
|
||||
+ // Luminol End - Raid revert
|
||||
if (blockPos != null) {
|
||||
this.started = true;
|
||||
this.spawnGroup(level, blockPos);
|
||||
@@ -387,7 +407,7 @@ public class Raid {
|
||||
i++;
|
||||
}
|
||||
|
||||
- if (i > 5) {
|
||||
+ if (i > (fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert ? 3 : 5)) { // Luminol - Raid revert
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
|
||||
this.stop();
|
||||
break;
|
||||
@@ -458,6 +478,17 @@ public class Raid {
|
||||
return blockPos != null ? Optional.of(blockPos) : Optional.empty();
|
||||
}
|
||||
|
||||
+ // Luminol Start - Raid revert
|
||||
+ private Optional<BlockPos> getValidSpawnPos(ServerLevel level, int n) {
|
||||
+ for (int i = 0; i < 3; ++i) {
|
||||
+ BlockPos blockPos = this.findRandomSpawnPos(level, n, 1);
|
||||
+ if (blockPos == null) continue;
|
||||
+ return Optional.of(blockPos);
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Luminol End - Raid revert
|
||||
+
|
||||
private boolean hasMoreWaves() {
|
||||
return this.hasBonusWave() ? !this.hasSpawnedBonusWave() : !this.isFinalWave();
|
||||
}
|
||||
@@ -683,7 +714,7 @@ public class Raid {
|
||||
int i2 = this.center.getX() + Mth.floor(Mth.cos(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f);
|
||||
int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f);
|
||||
int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3);
|
||||
- if (Mth.abs(height - this.center.getY()) <= 96) {
|
||||
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.heightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - Disable height check
|
||||
mutableBlockPos.set(i2, height, i3);
|
||||
if (!level.isVillage(mutableBlockPos) || i <= 7) {
|
||||
int i4 = 10;
|
||||
@@ -702,6 +733,26 @@ public class Raid {
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Luminol Start - Raid revert
|
||||
+ @Nullable
|
||||
+ private BlockPos findRandomSpawnPos(ServerLevel level, int n, int n2) {
|
||||
+ int n3 = 2 - n;
|
||||
+ BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
+ SpawnPlacementType spawnPlacementType = SpawnPlacements.getPlacementType(EntityType.RAVAGER);
|
||||
+ for (int i = 0; i < n2; ++i) {
|
||||
+ float f = level.random.nextFloat() * ((float)Math.PI * 2);
|
||||
+ int n4 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0f * (float)n3) + level.random.nextInt(5);
|
||||
+ int n5 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0f * (float)n3) + level.random.nextInt(5);
|
||||
+ int n6 = level.getHeight(Heightmap.Types.WORLD_SURFACE, n4, n5);
|
||||
+ mutableBlockPos.set(n4, n6, n5);
|
||||
+ if (level.isVillage(mutableBlockPos) && n < 2) continue;
|
||||
+ if (!level.hasChunksAt(mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10) || !level.isPositionEntityTicking(mutableBlockPos) || !spawnPlacementType.isSpawnPositionOk(level, mutableBlockPos, EntityType.RAVAGER) && (!level.getBlockState(mutableBlockPos.below()).is(Blocks.SNOW) || !level.getBlockState(mutableBlockPos).isAir())) continue;
|
||||
+ return mutableBlockPos;
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Luminol End - Raid revert
|
||||
+
|
||||
private boolean addWaveMob(ServerLevel level, int wave, Raider raider) {
|
||||
// Folia start - make raids thread-safe
|
||||
if (!this.ownsRaid(level)) {
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..510514e363f4816a6e286fb9b5488153e03c9e55 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -128,6 +128,41 @@ public abstract class Raider extends PatrollingMonster {
|
||||
|
||||
currentRaid.removeFromRaid(serverLevel, this, false);
|
||||
}
|
||||
+
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.effect && !this.hasRaid()) {
|
||||
+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
+ net.minecraft.world.entity.player.Player entityhuman = null;
|
||||
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ } else if (entity instanceof net.minecraft.world.entity.animal.wolf.Wolf wolf) {
|
||||
+ LivingEntity entityliving = wolf.getOwner();
|
||||
+ if (wolf.isTame() && entityliving instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (entityhuman != null && !itemstack.isEmpty() && this.isCaptain()) {
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect = entityhuman.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ int i = 1;
|
||||
+
|
||||
+ if (mobeffect != null) {
|
||||
+ i += mobeffect.getAmplifier();
|
||||
+ entityhuman.removeEffectNoUpdate(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ } else {
|
||||
+ --i;
|
||||
+ }
|
||||
+
|
||||
+ i = net.minecraft.util.Mth.clamp(i, 0, 4);
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
|
||||
+
|
||||
+ if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
|
||||
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
|
||||
+ }
|
||||
+ this.setPatrolLeader(false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
}
|
||||
|
||||
super.die(cause);
|
||||
@@ -156,7 +191,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
}
|
||||
|
||||
public boolean hasRaid() {
|
||||
- return this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null);
|
||||
+ return !fun.bm.lophine.config.modules.misc.RaidChangesConfig.selfCheck && (this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null)); // Leaves - Disable raid self check
|
||||
}
|
||||
|
||||
public boolean hasActiveRaid() {
|
||||
diff --git a/net/minecraft/world/item/component/OminousBottleAmplifier.java b/net/minecraft/world/item/component/OminousBottleAmplifier.java
|
||||
index 33907bb190ffa22ccf9ea424b1e536297878711a..2fca459f2c888079322f6b957bbee3ac0e33c4bc 100644
|
||||
--- a/net/minecraft/world/item/component/OminousBottleAmplifier.java
|
||||
+++ b/net/minecraft/world/item/component/OminousBottleAmplifier.java
|
||||
@@ -29,7 +29,7 @@ public record OminousBottleAmplifier(int value) implements ConsumableListener, T
|
||||
|
||||
@Override
|
||||
public void onConsume(Level level, LivingEntity entity, ItemStack stack, Consumable consumable) {
|
||||
- entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below
|
||||
+ entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below // Luminol - Raid effect infinite
|
||||
}
|
||||
|
||||
// Paper start - properly resend entities - collect packets for bundle
|
||||
@@ -41,7 +41,7 @@ public record OminousBottleAmplifier(int value) implements ConsumableListener, T
|
||||
|
||||
@Override
|
||||
public void addToTooltip(Item.TooltipContext context, Consumer<Component> tooltipAdder, TooltipFlag flag, DataComponentGetter componentGetter) {
|
||||
- List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true));
|
||||
+ List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Luminol - Raid effect infinite
|
||||
PotionContents.addPotionTooltip(list, tooltipAdder, 1.0F, context.tickRate());
|
||||
}
|
||||
}
|
||||
-154
@@ -1,154 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 29 Apr 2025 23:03:56 +0800
|
||||
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..6b7c92fdf562dfa46eee8e8acbc82b02fc3226c5 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1345,6 +1345,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
|
||||
killCredit.awardKillScore(this, cause);
|
||||
this.createWitherRose(killCredit);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity entitylivingnew = this.getKillCreditOrigin();
|
||||
+ if (entitylivingnew != null) {
|
||||
+ this.damageTransferToAsync(entitylivingnew, cause);
|
||||
+ }
|
||||
+ // 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
|
||||
}
|
||||
// Leaves end - exp fix
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ private void damageTransferToAsync(LivingEntity entity, DamageSource cause) {
|
||||
+ // Operations running on current entity
|
||||
+ this.awardStat(Stats.ENTITY_KILLED_BY.get(entity.getType()));
|
||||
+ this.createWitherRose(entity);
|
||||
+
|
||||
+ // the entity might be in another tickregion sometimes, so we need to schedule the task onto the entity
|
||||
+ // to ensure thread safe
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
|
||||
+ try {
|
||||
+ nmsEntity.awardKillScore(this, cause);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L );
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
private void tellNeutralMobsThatIDied() {
|
||||
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 d55a6989fd68f0bcf7bd05e9420fda1115afa6c0..5369a6597e48ed9f0d8f7f0b9685ce4950df4fe5 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
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol Start - raid revert adapt Cross Region Damage trace
|
||||
+ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent, boolean async) {
|
||||
+ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
|
||||
+ return addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true);
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ postToEntityThreadAddEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true);
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private void postToEntityThreadAddEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||
+ if (entity != null)
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> {
|
||||
+ try {
|
||||
+ addEffect(effectInstance, nmsEntity, cause, fireEvent);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L );
|
||||
+ }
|
||||
+ // Luminol End - raid revert adapt Cross Region Damage trace
|
||||
+
|
||||
public boolean canBeAffected(MobEffectInstance effectInstance) {
|
||||
if (this.getType().is(EntityTypeTags.IMMUNE_TO_INFESTED)) {
|
||||
return !effectInstance.is(MobEffects.INFESTED);
|
||||
@@ -1948,6 +1971,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
final LivingEntity killer = this.getKillCredit();
|
||||
if (killer != null) {
|
||||
killer.awardKillScore(this, damageSource);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity killernew = this.getKillCreditOrigin();
|
||||
+ if (killernew != null) {
|
||||
+ this.damageTransferToAsync(killernew, damageSource);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
}
|
||||
}); // Paper end
|
||||
this.postDeathDropItems(deathEvent); // Paper
|
||||
@@ -1958,6 +1988,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
return deathEvent; // Paper
|
||||
}
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ private void damageTransferToAsync(LivingEntity entity, DamageSource damageSource) {
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
|
||||
+ try {
|
||||
+ nmsEntity.awardKillScore(this, damageSource);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L );
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
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 +2598,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ @Nullable
|
||||
+ public LivingEntity getKillCreditOrigin() {
|
||||
+ if (this.lastHurtByPlayer != null) {
|
||||
+ return this.lastHurtByPlayer.getEntity(this.level(), Player.class);
|
||||
+ } else if (this.lastHurtByMob != null) {
|
||||
+ return this.lastHurtByMob.getEntity(this.level(), LivingEntity.class);
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
public final float getMaxHealth() {
|
||||
return (float)this.getAttributeValue(Attributes.MAX_HEALTH);
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index 510514e363f4816a6e286fb9b5488153e03c9e55..4638af10539a316acae64fb26881c8e699c496e0 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -157,7 +157,13 @@ 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, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
|
||||
|
||||
if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
|
||||
- entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
|
||||
+ // Luminol start - Raid changes adapt DamageSource trace
|
||||
+ if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true, true);
|
||||
+ } else {
|
||||
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
|
||||
+ }
|
||||
+ // Luminol end - Raid changes adapt DamageSource trace
|
||||
}
|
||||
this.setPatrolLeader(false);
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 29 Apr 2025 23:03:56 +0800
|
||||
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 ad50feba5cbc5fe904850e6da06a866eeb23b519..f7869f06ab29e4bbd003c807176345dec9e9e5ab 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1467,6 +1467,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.awardStat(Stats.ENTITY_KILLED_BY.get(killer.getType()));
|
||||
killer.awardKillScore(this, source);
|
||||
this.createWitherRose(killer);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity entitylivingnew = this.getKillCreditOrigin();
|
||||
+ if (entitylivingnew != null) {
|
||||
+ this.damageTransferToAsync(entitylivingnew, source);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
}
|
||||
|
||||
this.level().broadcastEntityEvent(this, EntityEvent.DEATH);
|
||||
@@ -1490,6 +1497,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
// Leaves end - exp fix
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ private void damageTransferToAsync(LivingEntity entity, DamageSource cause) {
|
||||
+ // Operations running on current entity
|
||||
+ this.awardStat(Stats.ENTITY_KILLED_BY.get(entity.getType()));
|
||||
+ this.createWitherRose(entity);
|
||||
+
|
||||
+ // the entity might be in another tickregion sometimes, so we need to schedule the task onto the entity
|
||||
+ // to ensure thread safe
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
|
||||
+ try {
|
||||
+ nmsEntity.awardKillScore(this, cause);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
private void tellNeutralMobsThatIDied() {
|
||||
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 cd2fb9e2110d0dba1358daa283af767db3f4e80a..cc7b2ea7fda1326e3f9ed46373190a05f60c4d34 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -1961,6 +1961,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
final LivingEntity killer = this.getKillCredit();
|
||||
if (killer != null) {
|
||||
killer.awardKillScore(this, source);
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
|
||||
+ final LivingEntity killernew = this.getKillCreditOrigin();
|
||||
+ if (killernew != null) {
|
||||
+ this.damageTransferToAsync(killernew, source);
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
}
|
||||
}); // Paper end
|
||||
this.postDeathDropItems(deathEvent); // Paper
|
||||
@@ -1971,6 +1978,19 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
return deathEvent; // Paper
|
||||
}
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ private void damageTransferToAsync(LivingEntity entity, DamageSource damageSource) {
|
||||
+ entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
|
||||
+ try {
|
||||
+ if (nmsEntity.isRemoved()) return;
|
||||
+ nmsEntity.awardKillScore(this, damageSource);
|
||||
+ } catch (Throwable ex) {
|
||||
+ LOGGER.error(ex.getMessage(), ex);
|
||||
+ }
|
||||
+ }, null, 1L );
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
protected void dropEquipment(final ServerLevel level) {
|
||||
}
|
||||
protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
|
||||
@@ -2629,6 +2649,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol Start - Cross Region Damage trace
|
||||
+ @Nullable
|
||||
+ public LivingEntity getKillCreditOrigin() {
|
||||
+ if (this.lastHurtByPlayer != null) {
|
||||
+ return this.lastHurtByPlayer.getEntity(this.level(), Player.class);
|
||||
+ } else if (this.lastHurtByMob != null) {
|
||||
+ return this.lastHurtByMob.getEntity(this.level(), LivingEntity.class);
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Luminol End - Cross Region Damage trace
|
||||
+
|
||||
public final float getMaxHealth() {
|
||||
return (float)this.getAttributeValue(Attributes.MAX_HEALTH);
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 16 Jan 2026 02:34:43 +0800
|
||||
Subject: [PATCH] Add config to enable save-all command
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index 11cacb26ce260373476dad764014ba1852477831..981f63b75584dbcb4bb0d5672e8c8bb140c52f9d 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -364,6 +364,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 89f61f5715942d2b521e04b9fdc8b1b379c0c957..2c2487e1c1c65438119a13bd705a9e44697955ed 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -299,7 +299,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 61983a80191e64942bfdac74c6d2f23cf781484d..99edebf474277e680df63930b51fef579b712def 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1686,6 +1686,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Folia start - region threading
|
||||
public void tickServer(final long startTime, final long scheduledEnd, final long targetBuffer,
|
||||
final io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
|
||||
+ // Lophine start - save-all fix
|
||||
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
|
||||
+ }
|
||||
+ // Lophine end - save-all fix
|
||||
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||
// Folia end - region threading
|
||||
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
index bc6d01996dde0870f6ebbda14176352777938a0c..8314d239435debf7aff947b7dd3bab83e3c80dc6 100644
|
||||
--- a/net/minecraft/server/commands/SaveAllCommand.java
|
||||
+++ b/net/minecraft/server/commands/SaveAllCommand.java
|
||||
@@ -21,7 +21,9 @@ public class SaveAllCommand {
|
||||
}
|
||||
|
||||
private static int saveAll(final CommandSourceStack source, final boolean flush) throws CommandSyntaxException {
|
||||
- source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
+ // Lophine start - save all
|
||||
+ fun.bm.lophine.utils.SaveAllUtil.preSaveAll(source, flush);
|
||||
+/* source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||
MinecraftServer server = source.getServer();
|
||||
boolean success = server.saveEverything(true, flush, true);
|
||||
if (!success) {
|
||||
@@ -29,6 +31,12 @@ public class SaveAllCommand {
|
||||
} else {
|
||||
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
|
||||
return 1;
|
||||
- }
|
||||
+ }*/
|
||||
+ return 1;
|
||||
}
|
||||
+
|
||||
+ public static SimpleCommandExceptionType getErrorFailed() {
|
||||
+ return ERROR_FAILED;
|
||||
+ }
|
||||
+ // Lophine end - save all
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 7 Jul 2025 16:30:54 +0800
|
||||
Subject: [PATCH] Add config to allow infinite trade
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
||||
index 79242037e868a140513f032e74e8594c0c6ff41c..8570c5089b605125680f8558ae201550df2d0a47 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.misc.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..28d743cc7beeb92a33683b8eea84096f94d90fb2 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.misc.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..21ec77d5167cfdf05043ea474165148fb2b0c2d9 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.misc.VillagerConfig.villagerInfiniteTrade); // Lophine - infinite trade
|
||||
}
|
||||
|
||||
public void setToOutOfStock() {
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 4 Sep 2025 02:14:16 +0800
|
||||
Subject: [PATCH] Add config to enable function command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 2c2487e1c1c65438119a13bd705a9e44697955ed..4e0428948d618b0a072679762dc3cb39d6e12c2f 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -217,7 +217,11 @@ public class Commands {
|
||||
FillCommand.register(this.dispatcher, context);
|
||||
FillBiomeCommand.register(this.dispatcher, context);
|
||||
ForceLoadCommand.register(this.dispatcher);
|
||||
- //FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
|
||||
+ // Lophine start - Add config to enable function command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.function) {
|
||||
+ FunctionCommand.register(this.dispatcher); // Folia - region threading - TODO
|
||||
+ }
|
||||
+ // Lophine end - Add config to enable function command
|
||||
GameModeCommand.register(this.dispatcher);
|
||||
GameRuleCommand.register(this.dispatcher, context);
|
||||
GiveCommand.register(this.dispatcher, context);
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 29 Sep 2025 22:56:03 +0800
|
||||
Subject: [PATCH] Add config to enable scoreboard command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 4e0428948d618b0a072679762dc3cb39d6e12c2f..87ffca5ff0c2775cb85a6058c9be66e00c94f01f 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -246,7 +246,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
|
||||
+ // Lophine start - Add a config to enable scoreboard command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.scoreboard) {
|
||||
+ ScoreboardCommand.register(this.dispatcher, context); // Folia - region threading
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable scoreboard command
|
||||
SeedCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
|
||||
VersionCommand.register(this.dispatcher, commandSelection != Commands.CommandSelection.INTEGRATED);
|
||||
SetBlockCommand.register(this.dispatcher, context);
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 7 Jul 2025 18:19:00 +0800
|
||||
Subject: [PATCH] Add config to enable unsafe waypoint bar
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index e2fc15d84fafde6847ecead23c55169449275e1b..b0a06cdfaa49237f372ecd131d47289160476b07 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -253,7 +253,11 @@ public class Commands {
|
||||
TimeCommand.register(this.dispatcher);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
||||
+ // Lophine start - unsafe waypoint bar
|
||||
+ if (fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) {
|
||||
+ 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..36e9b027ce5213f8914728293633e78e9905c1b2 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.WaypointConfig.forceEnableWaypointUnsafe) 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.WaypointConfig.forceEnableWaypointUnsafe) 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.WaypointConfig.forceEnableWaypointUnsafe) 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.WaypointConfig.forceEnableWaypointUnsafe) 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() {
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 4 Jun 2026 00:56:32 +0800
|
||||
Subject: [PATCH] Add config to enable trigger command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 87ffca5ff0c2775cb85a6058c9be66e00c94f01f..74ef76058e5a410d12f88aa09450e7d90f63b5e6 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -274,7 +274,11 @@ public class Commands {
|
||||
// Luminol end - Add a config to enable tick command
|
||||
TimeCommand.register(this.dispatcher, context);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
- //TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ // Lophine start - Add a config to enable trigger command
|
||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.trigger) {
|
||||
+ TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable trigger command
|
||||
if (me.earthme.luminol.config.modules.experiment.CommandConfig.waypointsAndWaypointCommand) WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later // Luminol - Restore waypoints
|
||||
WeatherCommand.register(this.dispatcher);
|
||||
WorldBorderCommand.register(this.dispatcher);
|
||||
@@ -1,198 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 3 Aug 2025 15:24:01 +0800
|
||||
Subject: [PATCH] Leaves: Leaves Protocol Core
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index 8405157ec35a443e238fa6866772c839621d73d7..4edb6e6e6287f232f7eef45c747554264ec05319 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -334,6 +334,8 @@ public final class RegionizedServer {
|
||||
}
|
||||
// Luminol end - Add a config to enable tick command
|
||||
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(tickCount); // Leaves - protocol
|
||||
+
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
@@ -443,6 +445,8 @@ public final class RegionizedServer {
|
||||
|
||||
world.updateTickData();
|
||||
|
||||
+ MinecraftServer.getServer().handleTickCount(tickCount); // Lophine - reuse tick count
|
||||
+
|
||||
world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); // required to eventually process ticket updates
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644
|
||||
--- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
+++ b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java
|
||||
@@ -40,13 +40,22 @@ public interface CustomPacketPayload {
|
||||
|
||||
@Override
|
||||
public void encode(B buffer, CustomPacketPayload value) {
|
||||
+ // Leaves start - protocol core
|
||||
+ if (value instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload payload) {
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.encode(buffer, payload);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - protocol core
|
||||
this.writeCap(buffer, value.type(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomPacketPayload decode(B buffer) {
|
||||
ResourceLocation resourceLocation = buffer.readResourceLocation();
|
||||
- return (CustomPacketPayload)this.findCodec(resourceLocation).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));
|
||||
+ // Leaves end - protocol core
|
||||
}
|
||||
};
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index a0f1db50adf5163a671d3d9e9df7adb7de4250c6..af13707933af14171447d5ab6faacb64ddf194a7 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
// Folia start - regionised ticking
|
||||
public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer();
|
||||
+ private int tickCount;
|
||||
|
||||
@Override
|
||||
public <V> CompletableFuture<V> submit(java.util.function.Supplier<V> task) {
|
||||
@@ -2226,9 +2227,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // Lophine start - reuse tick count
|
||||
public int getTickCount() {
|
||||
- throw new UnsupportedOperationException(); // Folia - region threading
|
||||
+ if (false) throw new UnsupportedOperationException(); // Folia - region threading
|
||||
+ return this.tickCount;
|
||||
+ }
|
||||
+
|
||||
+ public void handleTickCount(int tickCount1) {
|
||||
+ tickCount = tickCount1;
|
||||
}
|
||||
+ // Lophine end - reuse tick count
|
||||
|
||||
public int getSpawnProtectionRadius() {
|
||||
return 16;
|
||||
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 714813cba67da4a737682fe9276cb0d96fea336d..9677a3d62de11dafc8b9debe7a18ee6d14c7a64d 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
|
||||
public @Nullable String playerBrand;
|
||||
public final java.util.Set<String> pluginMessagerChannels;
|
||||
// Paper end - retain certain values
|
||||
+ public final GameProfile profile; // Leaves - protocol core
|
||||
|
||||
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie) {
|
||||
this.server = server;
|
||||
@@ -70,6 +71,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
this.pluginMessagerChannels = cookie.channels();
|
||||
this.keepAlive = cookie.keepAlive();
|
||||
// Paper end
|
||||
+ this.profile = cookie.gameProfile(); // Leaves - protocol core
|
||||
}
|
||||
|
||||
// Paper start - configuration phase API
|
||||
@@ -160,6 +162,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
@Override
|
||||
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
|
||||
+ // Leaves start - protocol
|
||||
+ if (packet.payload() instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload leavesPayload) {
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), leavesPayload);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.DiscardedPayload(net.minecraft.resources.ResourceLocation id, byte[] data)) {
|
||||
+ if (org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleBytebuf(org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this), id, io.netty.buffer.Unpooled.wrappedBuffer(data))) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - protocol
|
||||
+
|
||||
// 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
|
||||
final String channel = new String(data, from, length, java.nio.charset.StandardCharsets.US_ASCII);
|
||||
if (register) {
|
||||
bridge.addChannel(channel);
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleMinecraftRegister(channel, org.leavesmc.leaves.protocol.core.ProtocolUtils.createSelector(this)); // Leaves - protocol
|
||||
} else {
|
||||
bridge.removeChannel(channel);
|
||||
}
|
||||
- // Paper end
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -385,9 +400,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
net.minecraft.server.level.ServerPlayer player = serverGamePacketListener.player;
|
||||
org.bukkit.event.player.PlayerKickEvent.Cause cause = disconnectionDetails.disconnectionReason().orElseThrow().game().orElse(org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN);
|
||||
org.bukkit.event.player.PlayerKickEvent event = new org.bukkit.event.player.PlayerKickEvent(
|
||||
- player.getBukkitEntity(),
|
||||
- io.papermc.paper.adventure.PaperAdventure.asAdventure(disconnectionDetails.reason()),
|
||||
- rawLeaveMessage, cause
|
||||
+ player.getBukkitEntity(),
|
||||
+ io.papermc.paper.adventure.PaperAdventure.asAdventure(disconnectionDetails.reason()),
|
||||
+ rawLeaveMessage, cause
|
||||
|
||||
);
|
||||
|
||||
@@ -420,10 +435,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
private void disconnect0(DisconnectionDetails disconnectionDetails) {
|
||||
this.connection
|
||||
- .send(
|
||||
- new ClientboundDisconnectPacket(disconnectionDetails.reason()),
|
||||
- PacketSendListener.thenRun(() -> this.connection.disconnect(disconnectionDetails))
|
||||
- );
|
||||
+ .send(
|
||||
+ new ClientboundDisconnectPacket(disconnectionDetails.reason()),
|
||||
+ PacketSendListener.thenRun(() -> this.connection.disconnect(disconnectionDetails))
|
||||
+ );
|
||||
this.onDisconnect(disconnectionDetails);
|
||||
this.connection.setReadOnly();
|
||||
// CraftBukkit - Don't wait
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 4ef2816210f06082f2209c51d04aad6bb188232b..593dbcda4b497291eb1ecdc64b947a8d279f8be6 100644
|
||||
--- 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
|
||||
}
|
||||
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player);
|
||||
+
|
||||
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 {
|
||||
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) {
|
||||
+ 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 {
|
||||
serverPlayer.connection.send(clientboundUpdateRecipesPacket);
|
||||
serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer);
|
||||
}
|
||||
+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleDataPackReload(); // Leaves - protocol core
|
||||
}
|
||||
|
||||
public boolean isAllowCommandsForAllPlayers() {
|
||||
+30
-26
@@ -1,39 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <wangxyper@163.com>
|
||||
Date: Wed, 5 Feb 2025 15:22:19 +0800
|
||||
Subject: [PATCH] Add config to enable Raytracing tracker
|
||||
Subject: [PATCH] Add config to enable raytracing tracker
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd16792507f 100644
|
||||
index 0c0775bbb0c0ba0c37d1b884bb106b5250e94750..0dfb25ad032429a2aea7aa441dd5fd1848a6c617 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1278,7 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
double d1 = vec3_dx * vec3_dx + vec3_dz * vec3_dz; // Paper
|
||||
double d2 = d * d;
|
||||
@@ -1350,7 +1350,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
|
||||
double distanceSquared = deltaToPlayerX * deltaToPlayerX + deltaToPlayerZ * deltaToPlayerZ; // Paper
|
||||
double rangeSquared = visibleRange * visibleRange;
|
||||
// Paper start - Configurable entity tracking range by Y
|
||||
- boolean flag = d1 <= d2;
|
||||
+ boolean flag = d1 <= d2 && !entity.isCulled(); // Luminol - Ray tracing entity tracker
|
||||
if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
|
||||
- boolean visibleToPlayer = distanceSquared <= rangeSquared;
|
||||
+ boolean visibleToPlayer = distanceSquared <= rangeSquared && !entity.isCulled(); // Luminol - Ray tracing entity tracker
|
||||
if (visibleToPlayer && level.paperConfig().entities.trackingRangeY.enabled) {
|
||||
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
|
||||
if (rangeY != -1) {
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 2f733a3f75f9fe637864158a31d7507eac121d45..f7fcb4782b49374df8fe8f4401a4259f037221f7 100644
|
||||
index 552fd994ee30deb6e9f4228b17a2883cf26b164c..f090b8d77bd2731debfc61c263bd77550f52212b 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
|
||||
+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
|
||||
@@ -167,7 +167,7 @@ public abstract class Entity
|
||||
ItemOwner,
|
||||
SlotProvider,
|
||||
DebugValueSource,
|
||||
- TypedInstance<EntityType<?>>, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
|
||||
+ TypedInstance<EntityType<?>>, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
|
||||
// CraftBukkit start
|
||||
private static final int CURRENT_LEVEL = 2;
|
||||
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
|
||||
@@ -6439,4 +6439,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
static boolean isLevelAtLeast(ValueInput input, int level) {
|
||||
@@ -6432,4 +6432,48 @@ public abstract class Entity
|
||||
// Paper end - Expose entity id counter
|
||||
|
||||
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
||||
+ // Lophine start - Add config to enable raytracing tracker
|
||||
+
|
||||
+ private long lasttime = 0;
|
||||
+ private boolean culled = false;
|
||||
@@ -76,26 +77,29 @@ index 2f733a3f75f9fe637864158a31d7507eac121d45..f7fcb4782b49374df8fe8f4401a4259f
|
||||
+ return this.outOfCamera;
|
||||
+ }
|
||||
+
|
||||
+ // Lophine end - Add config to enable raytracing tracker
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
|
||||
index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b706e3273 100644
|
||||
index cb0a52dc3795e1cf54069bcbe82abf7877a658b8..0d743a01ae70baa789cd0e0bb9abd4c4f8310b99 100644
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -1119,6 +1119,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
@@ -1252,6 +1252,11 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
|
||||
public final int passengerTickTimerId;
|
||||
public final int passengerInactiveTickTimerId;
|
||||
// Folia end - profiler
|
||||
+ // Lophine start - Add config to enable raytracing tracker
|
||||
+ // Luminol - Raytracing entity tracker
|
||||
+ public boolean skipRaytracningCheck = false;
|
||||
+ // Luminol end
|
||||
+ // Lophine end - Add config to enable raytracing tracker
|
||||
|
||||
public EntityType(
|
||||
EntityType.EntityFactory<T> factory,
|
||||
final EntityType.EntityFactory<T> factory,
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a6268fdaa46 100644
|
||||
index ce8ab4b7eee5e0715e780d189d2f6554c5a9dc3c..06c6d30f3aef605bc25c42db8a6d26bbde57f40b 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 {
|
||||
@@ -186,6 +186,25 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -119,9 +123,9 @@ index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a62
|
||||
+ }
|
||||
+ // Luminol end
|
||||
|
||||
public Player(Level level, GameProfile gameProfile) {
|
||||
public Player(final Level level, final GameProfile gameProfile) {
|
||||
super(EntityType.PLAYER, level);
|
||||
@@ -287,6 +306,26 @@ public abstract class Player extends LivingEntity {
|
||||
@@ -241,6 +260,26 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
@@ -148,8 +152,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()) {
|
||||
@@ -1355,6 +1394,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
if (this.hasContainerOpen()) {
|
||||
this.doCloseContainer();
|
||||
}
|
||||
+ if (this.cullTask != null) this.cullTask.signalStop(); // Luminol - Ray tracing entity tracker
|
||||
@@ -1,62 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 27 Jul 2025 13:48:10 +0800
|
||||
Subject: [PATCH] Leaves: Disable packet limit
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/6a2b9ee6b330cd18b0a8eb2a824d561fa76012bb/leaves-server/minecraft-patches/features/0043-Disable-packet-limit.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 9c7366fce56f2c8105c2e5b48f8d618e028f2604..7ab1d97081ffa8cd7ce69cf3165a312697f1fdbc 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -281,8 +281,8 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (this.stopReadingPackets) {
|
||||
return;
|
||||
}
|
||||
- if (this.allPacketCounts != null ||
|
||||
- io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ if (!fun.bm.lophine.config.modules.optimizations.NetworkConfig.disablePacketLimit && (this.allPacketCounts != null || // Leaves - can disable
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass()))) { // Leaves - can disable
|
||||
long time = System.nanoTime();
|
||||
synchronized (PACKET_LIMIT_LOCK) {
|
||||
if (this.allPacketCounts != null) {
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 227f0c315582b9c499915bebfb820049839466e6..1d52376f034dc5690e8b399512146b47b92c3c14 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -856,7 +856,7 @@ public class ServerGamePacketListenerImpl
|
||||
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
|
||||
// PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); // Paper - AsyncTabCompleteEvent; run this async
|
||||
// CraftBukkit start
|
||||
- if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits
|
||||
+ if (!fun.bm.lophine.config.modules.optimizations.NetworkConfig.disablePacketLimit && !this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits // Leaves - can disable
|
||||
this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -2047,6 +2047,7 @@ public class ServerGamePacketListenerImpl
|
||||
private static int getSpamThreshold() { return io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.incomingPacketThreshold; } // Paper - Configurable threshold
|
||||
|
||||
private boolean checkLimit(long timestamp) {
|
||||
+ if (fun.bm.lophine.config.modules.optimizations.NetworkConfig.disablePacketLimit) return true; // Leaves - disable
|
||||
if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < getSpamThreshold() && this.limitedPackets++ >= 8) { // Paper - Configurable threshold; raise packet limit to 8
|
||||
return false;
|
||||
}
|
||||
@@ -2586,6 +2587,7 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
// Spigot start - spam exclusions
|
||||
private void detectRateSpam(String message) {
|
||||
+ if (fun.bm.lophine.config.modules.optimizations.NetworkConfig.disablePacketLimit) return; // Leaves - disable
|
||||
// CraftBukkit start - replaced with thread safe throttle
|
||||
if (org.spigotmc.SpigotConfig.enableSpamExclusions) {
|
||||
for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
@@ -3335,7 +3337,7 @@ public class ServerGamePacketListenerImpl
|
||||
@Override
|
||||
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
|
||||
// Paper start - auto recipe limit
|
||||
- if (!org.bukkit.Bukkit.isPrimaryThread()) {
|
||||
+ if (!fun.bm.lophine.config.modules.optimizations.NetworkConfig.disablePacketLimit && !org.bukkit.Bukkit.isPrimaryThread()) { // Leaves - can disable
|
||||
if (!this.recipeSpamPackets.isIncrementAndUnderThreshold()) {
|
||||
this.disconnectAsync(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
@@ -0,0 +1,123 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 21 Jan 2026 21:28:21 +0800
|
||||
Subject: [PATCH] Add tick rate support
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index 981f63b75584dbcb4bb0d5672e8c8bb140c52f9d..6e8ee04967afa410ce9dccff34bf9a43201694fd 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -371,6 +371,14 @@ public final class RegionizedServer {
|
||||
this.globalTick(world, tickCount);
|
||||
}
|
||||
|
||||
+ // Lophine start - Add a config to enable tick command
|
||||
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
|
||||
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
|
||||
+ rateManager.reduceSprintTicks();
|
||||
+ rateManager.endTickWork();
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable tick command
|
||||
+
|
||||
// tick connections
|
||||
this.tickConnections();
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index 86c51506c518ee445d00f7eef36ee2c9adbd9b4c..a37f392146ccc0319cf56ee0058ae8782b598fe3 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
- public static final int TICK_RATE = 20;
|
||||
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
|
||||
+ public static float TICK_RATE = 20; // Lophine - Add tick command support
|
||||
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Lophine - Add tick command support
|
||||
// Folia start - watchdog
|
||||
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
|
||||
static {
|
||||
@@ -509,8 +509,24 @@ public final class TickRegionScheduler {
|
||||
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
|
||||
final long tickStart = System.nanoTime();
|
||||
|
||||
- // use max(), don't assume that tickStart >= scheduledStart
|
||||
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ // Lophine start - Add a config to enable tick command
|
||||
+ final long tickCount;
|
||||
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
|
||||
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
|
||||
+ if (rateManager.isSprinting() && rateManager.checkShouldSprintThisTick()) {
|
||||
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
|
||||
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
|
||||
+ tickCount = 1;
|
||||
+ } else {
|
||||
+ TICK_RATE = rateManager.tickrate();
|
||||
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
|
||||
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ }
|
||||
+ } else {
|
||||
+ // use max(), don't assume that tickStart >= scheduledStart
|
||||
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
|
||||
+ }
|
||||
+ // Lophine end - Add a config to enable tick command
|
||||
|
||||
if (!this.tryMarkTicking()) {
|
||||
if (!this.cancelled.get()) {
|
||||
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
|
||||
index 8d0f810100a4eac65831913feeb9a9eeb0e6006a..ca35415e152dc63cb9f4ae8da8b06766600922fd 100644
|
||||
--- a/net/minecraft/server/ServerTickRateManager.java
|
||||
+++ b/net/minecraft/server/ServerTickRateManager.java
|
||||
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
return false;
|
||||
} else if (this.remainingSprintTicks > 0L) {
|
||||
this.sprintTickStartTime = System.nanoTime();
|
||||
- this.remainingSprintTicks--;
|
||||
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
|
||||
return true;
|
||||
} else {
|
||||
this.finishTickSprint();
|
||||
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Lophine start - Add tick command support
|
||||
+ public void reduceSprintTicks() {
|
||||
+ this.remainingSprintTicks--;
|
||||
+ }
|
||||
+ // Lophine end - Add tick command support
|
||||
+
|
||||
public void endTickWork() {
|
||||
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
|
||||
}
|
||||
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
|
||||
index cae943bae4701f74b46a49d68da83ae797841590..9f43eff6160ac6855c2e5dd9c23c384b03b7e96c 100644
|
||||
--- a/net/minecraft/server/commands/TickCommand.java
|
||||
+++ b/net/minecraft/server/commands/TickCommand.java
|
||||
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
|
||||
import net.minecraft.util.TimeUtil;
|
||||
|
||||
public class TickCommand {
|
||||
- private static final float MAX_TICKRATE = 10000.0F;
|
||||
+ public static final float MAX_TICKRATE = 10000.0F; // Lophine - Add tick command support
|
||||
private static final String DEFAULT_TICKRATE = String.valueOf(20);
|
||||
|
||||
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
@@ -22,14 +22,14 @@ public class TickCommand {
|
||||
Commands.literal("tick")
|
||||
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
|
||||
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
|
||||
-/* .then(
|
||||
+ .then( // Lophine - Add tick rate support
|
||||
Commands.literal("rate")
|
||||
.then(
|
||||
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
|
||||
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
|
||||
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
|
||||
)
|
||||
- )*/
|
||||
+ )
|
||||
.then(
|
||||
Commands.literal("step")
|
||||
.executes(c -> step(c.getSource(), 1))
|
||||
@@ -1,472 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 26 Jul 2025 01:11:54 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/46cccfc39cafbca1681620d03947bc3ad558327f/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
index 643797124fe5a4489d0b7419b7e600c04f283ef2..04b4100da96aad50f08e8c59200eec934e7e873d 100644
|
||||
--- a/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
+++ b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
@@ -39,11 +39,13 @@ public class ItemInput {
|
||||
public ItemStack createItemStack(int count, boolean allowOversizedStacks) throws CommandSyntaxException {
|
||||
ItemStack itemStack = new ItemStack(this.item, count);
|
||||
itemStack.applyComponents(this.components);
|
||||
- if (allowOversizedStacks && count > itemStack.getMaxStackSize()) {
|
||||
- throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (allowOversizedStacks && count > org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)) {
|
||||
+ throw ERROR_STACK_TOO_BIG.create(this.getItemName(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack));
|
||||
} else {
|
||||
return itemStack;
|
||||
}
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
public String serialize(HolderLookup.Provider levelRegistry) {
|
||||
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
|
||||
index f7002d6752aa03603eb06e298ba1d7130cf13826..72c87f7c0392d087440db9d267a608598f6feb6d 100644
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -55,7 +55,7 @@ public class GiveCommand {
|
||||
private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
|
||||
ItemStack itemStack = item.createItemStack(1, false);
|
||||
final Component displayName = itemStack.getDisplayName(); // Paper - get display name early
|
||||
- int maxStackSize = itemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
int i = maxStackSize * 100;
|
||||
if (count > i) {
|
||||
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName()));
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 1d52376f034dc5690e8b399512146b47b92c3c14..4b215dc69887df9382bde4cfa2f37afadfe1bcb2 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3079,7 +3079,7 @@ public class ServerGamePacketListenerImpl
|
||||
} else if (slot.mayPlace(cursor)) {
|
||||
if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
|
||||
int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1;
|
||||
- toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount());
|
||||
+ toPlace = Math.min(toPlace, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(clickedItem) - clickedItem.getCount()); // Leaves - item over-stack util
|
||||
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
|
||||
if (toPlace == 1) {
|
||||
action = InventoryAction.PLACE_ONE;
|
||||
@@ -3115,7 +3115,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
|
||||
if (clickedItem.getCount() >= 0) {
|
||||
- if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) {
|
||||
+ if (clickedItem.getCount() + cursor.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(cursor)) { // Leaves - item over-stack util
|
||||
// As of 1.5, this is result slots only
|
||||
action = InventoryAction.PICKUP_ALL;
|
||||
}
|
||||
@@ -3326,6 +3326,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.containerMenu.broadcastFullState();
|
||||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.broadcastCarriedItem(); // Leaves - item over-stack util - force send carried item
|
||||
}
|
||||
if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
@@ -3437,7 +3438,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
|
||||
- boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
|
||||
+ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
|
||||
// CraftBukkit start - Call click event
|
||||
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
|
||||
@@ -3479,6 +3480,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - item over-stack util - force send carried item
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else if (flag && flag2) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
|
||||
index b382665cc125b8b5c0938e5e55984e4bf91d37ff..86cac164a2bf0e76528396e6aabbfd64cfc29559 100644
|
||||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable<ItemStack> {
|
||||
return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ default int getMaxStackLeaves(ItemStack stack) {
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack));
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
void setChanged();
|
||||
|
||||
boolean stillValid(Player player);
|
||||
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
|
||||
index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab630b0e54e 100644
|
||||
--- a/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/net/minecraft/world/SimpleContainer.java
|
||||
@@ -211,7 +211,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
@Override
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.items.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
}
|
||||
|
||||
private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) {
|
||||
- int maxStackSize = this.getMaxStackSize(other);
|
||||
+ int maxStackSize = this.getMaxStackLeaves(other); // Leaves - item over-stack util
|
||||
int min = Math.min(stack.getCount(), maxStackSize - other.getCount());
|
||||
if (min > 0) {
|
||||
other.grow(min);
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index b745eb5d9c68547335247910ff2ae8d5fb36349c..0c2bf0f8edb34a9011092ea94e54f7bbcee0bbbc 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -279,10 +279,15 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
|
||||
private boolean isMergable() {
|
||||
ItemStack item = this.getItem();
|
||||
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
|
||||
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item); // Paper - Alternative item-despawn-rate // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
private void tryToMerge(ItemEntity itemEntity) {
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.tryStackItems(this, itemEntity)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
ItemStack item = this.getItem();
|
||||
ItemStack item1 = itemEntity.getItem();
|
||||
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0c59f7654 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -165,10 +165,12 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) {
|
||||
+ // Leaves start - item over-stack util
|
||||
return !destination.isEmpty()
|
||||
- && destination.isStackable()
|
||||
- && destination.getCount() < this.getMaxStackSize(destination)
|
||||
+ && org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(destination)
|
||||
+ && destination.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(destination)
|
||||
&& ItemStack.isSameItemSameComponents(destination, origin); // Paper - check if itemstack is stackable first
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
// CraftBukkit start - Watch method above! :D
|
||||
@@ -181,7 +183,7 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
|
||||
- remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -190,7 +192,7 @@ public class Inventory implements Container, Nameable {
|
||||
|
||||
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
|
||||
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
|
||||
- remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -314,7 +316,7 @@ public class Inventory implements Container, Nameable {
|
||||
this.setItem(slot, item);
|
||||
}
|
||||
|
||||
- int i = this.getMaxStackSize(item) - item.getCount();
|
||||
+ int i = this.getMaxStackLeaves(item) - item.getCount(); // Leaves - item over-stack util
|
||||
int min = Math.min(count, i);
|
||||
if (min == 0) {
|
||||
return count;
|
||||
@@ -420,7 +422,7 @@ public class Inventory implements Container, Nameable {
|
||||
break;
|
||||
}
|
||||
|
||||
- int i = stack.getMaxStackSize() - this.getItem(slotWithRemainingSpace).getCount();
|
||||
+ int i = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Leaves - item over-stack util
|
||||
if (this.add(slotWithRemainingSpace, stack.split(i)) && sendPacket && this.player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.connection.send(this.createInventoryUpdatePacket(slotWithRemainingSpace));
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
index 83ccde54c625d40dc595e000c533f60aa929bd5a..6779503888e6d311758cffde582b0efbd66a33de 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
@@ -23,7 +23,7 @@ public class StackedItemContents {
|
||||
}
|
||||
|
||||
public void accountStack(ItemStack stack) {
|
||||
- this.accountStack(stack, stack.getMaxStackSize());
|
||||
+ this.accountStack(stack, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public void accountStack(ItemStack stack, int maxStackSize) {
|
||||
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a76381cee 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default void setChestVehicleItem(int slot, ItemStack stack) {
|
||||
this.unpackChestVehicleLootTable(null);
|
||||
this.getItemStacks().set(slot, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
default SlotAccess getChestVehicleSlot(final int index) {
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 9d8ab94f84f4523a2562f9eeb3410554e4269e46..87d1cf9ddfb3124069ff3ff921f2e62589562220 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -295,6 +295,13 @@ public abstract class AbstractContainerMenu {
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ public void sendSingleSlot(int slotIndex, ItemStack item) {
|
||||
+ if (this.synchronizer != null) {
|
||||
+ this.synchronizer.sendSlotChange(this, slotIndex, item);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
private void updateDataSlotListeners(int slotIndex, int value) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, slotIndex, value);
|
||||
@@ -451,7 +458,7 @@ public abstract class AbstractContainerMenu {
|
||||
&& (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size())
|
||||
&& this.canDragTo(slot1)) {
|
||||
int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0;
|
||||
- int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack));
|
||||
+ int min = Math.min(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Leaves - item over-stack util
|
||||
int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min);
|
||||
count -= min1 - i2;
|
||||
// slot1.setByPlayer(itemStack.copyWithCount(min1));
|
||||
@@ -563,7 +570,7 @@ public abstract class AbstractContainerMenu {
|
||||
slot.setByPlayer(carried2);
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(carried, carried2)) {
|
||||
- Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player);
|
||||
+ Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried2) - carried2.getCount(), player); // Leaves - item over-stack util
|
||||
optional1.ifPresent(itemStack2 -> {
|
||||
carried2.grow(itemStack2.getCount());
|
||||
slot.onTake(player, itemStack2);
|
||||
@@ -625,7 +632,7 @@ public abstract class AbstractContainerMenu {
|
||||
Slot slot2 = this.slots.get(slotId);
|
||||
if (slot2.hasItem()) {
|
||||
ItemStack itemStack = slot2.getItem();
|
||||
- this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize()));
|
||||
+ this.setCarried(itemStack.copyWithCount(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack))); // Leaves - item over-stack util
|
||||
}
|
||||
} else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) {
|
||||
Slot slot2 = this.slots.get(slotId);
|
||||
@@ -656,15 +663,15 @@ public abstract class AbstractContainerMenu {
|
||||
int maxStackSize = button == 0 ? 1 : -1;
|
||||
|
||||
for (int i3 = 0; i3 < 2; i3++) {
|
||||
- for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < itemStack.getMaxStackSize(); i4 += maxStackSize) {
|
||||
+ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); i4 += maxStackSize) { // Leaves - item over-stack util
|
||||
Slot slot3 = this.slots.get(i4);
|
||||
if (slot3.hasItem()
|
||||
&& canItemQuickReplace(slot3, itemStack, true)
|
||||
&& slot3.mayPickup(player)
|
||||
&& this.canTakeItemForPickAll(itemStack, slot3)) {
|
||||
ItemStack item1 = slot3.getItem();
|
||||
- if (i3 != 0 || item1.getCount() != item1.getMaxStackSize()) {
|
||||
- ItemStack itemStack1 = slot3.safeTake(item1.getCount(), itemStack.getMaxStackSize() - itemStack.getCount(), player);
|
||||
+ if (i3 != 0 || item1.getCount() != org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item1)) { // Leaves - item over-stack util
|
||||
+ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) - itemStack.getCount(), player); // Leaves - item over-stack util
|
||||
itemStack.grow(itemStack1.getCount());
|
||||
}
|
||||
}
|
||||
@@ -766,7 +773,7 @@ public abstract class AbstractContainerMenu {
|
||||
i = endIndex - 1;
|
||||
}
|
||||
|
||||
- if (stack.isStackable()) {
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(stack)) { // Leaves - item over-stack util
|
||||
while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) {
|
||||
Slot slot = this.slots.get(i);
|
||||
ItemStack item = slot.getItem();
|
||||
@@ -867,7 +874,7 @@ public abstract class AbstractContainerMenu {
|
||||
public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) {
|
||||
boolean flag = slot == null || !slot.hasItem();
|
||||
return !flag && ItemStack.isSameItemSameComponents(stack, slot.getItem())
|
||||
- ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize()
|
||||
+ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack) // Leaves - item over-stack util
|
||||
: flag;
|
||||
}
|
||||
|
||||
@@ -875,7 +882,7 @@ public abstract class AbstractContainerMenu {
|
||||
return switch (type) {
|
||||
case 0 -> Mth.floor((float)stack.getCount() / slots.size());
|
||||
case 1 -> 1;
|
||||
- case 2 -> stack.getMaxStackSize();
|
||||
+ case 2 -> org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack); // Leaves - item over-stack util
|
||||
default -> stack.getCount();
|
||||
};
|
||||
}
|
||||
@@ -897,7 +904,7 @@ public abstract class AbstractContainerMenu {
|
||||
for (int i = 0; i < container.getContainerSize(); i++) {
|
||||
ItemStack item = container.getItem(i);
|
||||
if (!item.isEmpty()) {
|
||||
- f += (float)item.getCount() / container.getMaxStackSize(item);
|
||||
+ f += Math.clamp((float) item.getCount() / container.getMaxStackSize(item), 0f, 1f); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..1a593d5bfc4574fd071604105422cd1d395648b8 100644
|
||||
--- a/net/minecraft/world/inventory/MerchantContainer.java
|
||||
+++ b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
@@ -109,7 +109,7 @@ public class MerchantContainer implements Container {
|
||||
@Override
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.itemStacks.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
if (this.isPaymentSlot(index)) {
|
||||
this.updateSellItem();
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
|
||||
index 5ceb8964476b40db4511bec91ff13c4f522a1357..f416d7976e41a06b5a8be93485eaa233ffceda5c 100644
|
||||
--- a/net/minecraft/world/inventory/Slot.java
|
||||
+++ b/net/minecraft/world/inventory/Slot.java
|
||||
@@ -75,7 +75,7 @@ public class Slot {
|
||||
}
|
||||
|
||||
public int getMaxStackSize(ItemStack stack) {
|
||||
- return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index 6154da1158756cff072d7e8cae10e20eafed1eec..93bbe7b473b8150954f06602a9f311867fe9a550 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -162,7 +162,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
@Deprecated
|
||||
@Nullable
|
||||
private Item item;
|
||||
- PatchedDataComponentMap components;
|
||||
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
|
||||
@Nullable
|
||||
private Entity entityRepresentation;
|
||||
|
||||
@@ -189,7 +189,8 @@ public final class ItemStack implements DataComponentHolder {
|
||||
} else {
|
||||
Holder<Item> holder = Item.STREAM_CODEC.decode(buffer);
|
||||
DataComponentPatch dataComponentPatch = codec.decode(buffer);
|
||||
- return new ItemStack(holder, varInt, dataComponentPatch);
|
||||
+ ItemStack itemStack = new ItemStack(holder, varInt, dataComponentPatch);
|
||||
+ return org.leavesmc.leaves.util.ItemOverstackUtils.decodeMaxStackSize(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +199,15 @@ public final class ItemStack implements DataComponentHolder {
|
||||
if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
|
||||
buffer.writeVarInt(0);
|
||||
} else {
|
||||
- buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count
|
||||
- Item.STREAM_CODEC.encode(buffer, value.getItemHolder());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ final ItemStack itemStack = org.leavesmc.leaves.util.ItemOverstackUtils.encodeMaxStackSize(value.copy());
|
||||
+ buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count
|
||||
+ Item.STREAM_CODEC.encode(buffer, itemStack.getItemHolder());
|
||||
// Paper start - adventure; conditionally render translatable components
|
||||
boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
|
||||
- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(value))) { // pass the itemstack as context to the obfuscation session
|
||||
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
|
||||
- codec.encode(buffer, value.components.asPatch());
|
||||
+ codec.encode(buffer, itemStack.components.asPatch());
|
||||
} finally {
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
|
||||
}
|
||||
@@ -299,7 +302,7 @@ public final class ItemStack implements DataComponentHolder {
|
||||
|
||||
for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) {
|
||||
int count = itemStack.getCount();
|
||||
- int maxStackSize = itemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (count > maxStackSize) {
|
||||
return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize);
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8c8a1e5d1 100644
|
||||
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
@@ -192,7 +192,7 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||
Direction direction = state.getValue(ORIENTATION).front();
|
||||
Container containerAt = HopperBlockEntity.getContainerAt(level, pos.relative(direction));
|
||||
ItemStack itemStack = stack.copy();
|
||||
- if (containerAt != null && (containerAt instanceof CrafterBlockEntity || stack.getCount() > containerAt.getMaxStackSize(stack))) {
|
||||
+ if (containerAt != null && (containerAt instanceof CrafterBlockEntity || stack.getCount() > containerAt.getMaxStackLeaves(stack))) { // Leaves - item over-stack util
|
||||
// CraftBukkit start - InventoryMoveItemEvent
|
||||
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index 36a72a11d28f99bfe85868461925b778cc01478e..2a9f204a514d697178fb3ffac25aece0024f0347 100644
|
||||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -409,7 +409,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
ItemStack itemStack = this.items.get(index);
|
||||
boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, stack);
|
||||
this.items.set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
if (index == 0 && !flag && this.level instanceof ServerLevel serverLevel) {
|
||||
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
index 5a094257a31f0500278a706a418e1697f8810ffb..63d6a43dab067aa4c8fb67095c455130196eef9f 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
@@ -145,7 +145,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack stack) {
|
||||
this.getItems().set(slot, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 5de769e7bd56bb3355c3c711d46ce5e103ea4409..8ba900fda7cce45679cde2b8b3272654129135ca 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -123,7 +123,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public void setItem(int index, ItemStack stack) {
|
||||
this.unpackLootTable(null);
|
||||
this.getItems().set(index, stack);
|
||||
- stack.limitSize(this.getMaxStackSize(stack));
|
||||
+ stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -690,9 +690,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (item.isEmpty()) {
|
||||
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
||||
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||
- if (!stack.isEmpty() && stack.getCount() > destination.getMaxStackSize()) {
|
||||
+ if (!stack.isEmpty() && (stack.getCount() > destination.getMaxStackSize() || stack.getCount() > stack.getMaxStackSize())) { // Leaves - item over-stack util
|
||||
leftover = stack; // Paper - Make hoppers respect inventory max stack size
|
||||
- stack = stack.split(destination.getMaxStackSize());
|
||||
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
|
||||
}
|
||||
// Spigot end
|
||||
IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading
|
||||
@@ -1,153 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 23 Jul 2025 20:28:40 +0800
|
||||
Subject: [PATCH] Leaves: Redstone Shears Wrench
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/bfde470a867b74d177fe1b9a2a3ed5c49cd126c7/leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
|
||||
index 8cf3e51e12f9cf98836657e722edb23943f9e866..155693a18bb641a930a000bc9b1ccfc853e1bae5 100644
|
||||
--- a/net/minecraft/world/item/ShearsItem.java
|
||||
+++ b/net/minecraft/world/item/ShearsItem.java
|
||||
@@ -24,6 +24,30 @@ import net.minecraft.world.level.block.GrowingPlantHeadBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
|
||||
+// Leaves start - shears wrench
|
||||
+import net.minecraft.Util;
|
||||
+import net.minecraft.network.chat.Component;
|
||||
+import net.minecraft.world.level.block.ComparatorBlock;
|
||||
+import net.minecraft.world.level.block.DispenserBlock;
|
||||
+import net.minecraft.world.level.block.HopperBlock;
|
||||
+import net.minecraft.world.level.block.ObserverBlock;
|
||||
+import net.minecraft.world.level.block.RepeaterBlock;
|
||||
+import net.minecraft.world.level.block.CrafterBlock;
|
||||
+import net.minecraft.world.level.block.LeverBlock;
|
||||
+import net.minecraft.world.level.block.CocoaBlock;
|
||||
+import net.minecraft.world.level.block.TrapDoorBlock;
|
||||
+import net.minecraft.world.level.block.FenceGateBlock;
|
||||
+import net.minecraft.world.level.block.LightningRodBlock;
|
||||
+import net.minecraft.world.level.block.RailBlock;
|
||||
+import net.minecraft.world.level.block.BaseRailBlock;
|
||||
+import net.minecraft.world.level.block.PoweredRailBlock;
|
||||
+import net.minecraft.world.level.block.CalibratedSculkSensorBlock;
|
||||
+import net.minecraft.world.level.block.piston.PistonBaseBlock;
|
||||
+import net.minecraft.world.level.block.state.StateDefinition;
|
||||
+import net.minecraft.world.level.block.state.properties.RailShape;
|
||||
+import net.minecraft.world.level.block.state.properties.Property;
|
||||
+// Leaves end - shears wrench
|
||||
+
|
||||
public class ShearsItem extends Item {
|
||||
public ShearsItem(Item.Properties properties) {
|
||||
super(properties);
|
||||
@@ -80,7 +104,108 @@ public class ShearsItem extends Item {
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
+ // Leaves start - shears wrench
|
||||
+ Block block = blockState.getBlock();
|
||||
+ if (fun.bm.lophine.config.modules.misc.RedStoneConfig.shears && (
|
||||
+ block instanceof ObserverBlock ||
|
||||
+ block instanceof DispenserBlock ||
|
||||
+ block instanceof PistonBaseBlock ||
|
||||
+ block instanceof HopperBlock ||
|
||||
+ block instanceof RepeaterBlock ||
|
||||
+ block instanceof ComparatorBlock ||
|
||||
+ block instanceof CrafterBlock ||
|
||||
+ block instanceof LeverBlock ||
|
||||
+ block instanceof CocoaBlock ||
|
||||
+ block instanceof TrapDoorBlock ||
|
||||
+ block instanceof FenceGateBlock ||
|
||||
+ block instanceof LightningRodBlock ||
|
||||
+ block instanceof CalibratedSculkSensorBlock ||
|
||||
+ block instanceof BaseRailBlock
|
||||
+ )) {
|
||||
+ StateDefinition<Block, BlockState> blockstatelist = block.getStateDefinition();
|
||||
+ Property<?> iblockstate;
|
||||
+ if (block instanceof CrafterBlock) iblockstate = blockstatelist.getProperty("orientation");
|
||||
+ else if (block instanceof BaseRailBlock) iblockstate = blockstatelist.getProperty("shape");
|
||||
+ else iblockstate = blockstatelist.getProperty("facing");
|
||||
+ Player player = context.getPlayer();
|
||||
+
|
||||
+ if (iblockstate == null || player == null) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (block instanceof BaseRailBlock) {
|
||||
+ if (block instanceof RailBlock) {
|
||||
+ if (blockState.getValue(RailBlock.SHAPE).isSlope()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (getNameHelper(blockState, PoweredRailBlock.POWERED).equals("true")) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ if (blockState.getValue(PoweredRailBlock.SHAPE).isSlope()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (block instanceof PistonBaseBlock) {
|
||||
+ if (getNameHelper(blockState, PistonBaseBlock.EXTENDED).equals("true")) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (block instanceof RepeaterBlock || block instanceof ComparatorBlock) {
|
||||
+ if (getNameHelper(blockState, ComparatorBlock.POWERED).equals("true")) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ if (block instanceof RepeaterBlock) {
|
||||
+ if (getNameHelper(blockState, RepeaterBlock.LOCKED).equals("true")) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (block instanceof CrafterBlock) {
|
||||
+ if (getNameHelper(blockState, CrafterBlock.CRAFTING).equals("true")) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ BlockState iblockdata1 = ShearsItem.cycleState(blockState, iblockstate, player.isSecondaryUseActive());
|
||||
+ level.setBlock(clickedPos, iblockdata1, 18);
|
||||
+ ShearsItem.message(player, Component.translatable("item.minecraft.debug_stick.update", iblockstate.getName(), ShearsItem.getNameHelper(iblockdata1, iblockstate)));
|
||||
+ return InteractionResult.CONSUME;
|
||||
+ }
|
||||
+ // Leaves end - shears wrench
|
||||
+
|
||||
return super.useOn(context);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaves start - shears wrench
|
||||
+ private static <T extends Comparable<T>> BlockState cycleState(BlockState state, Property<T> property, boolean inverse) {
|
||||
+ List<T> possibleValues = property.getPossibleValues();
|
||||
+ if (possibleValues.getFirst() instanceof RailShape) {
|
||||
+ boolean isRailBlock = state.getBlock() instanceof RailBlock;
|
||||
+ possibleValues = possibleValues.stream().filter(possibleValue -> {
|
||||
+ RailShape shape = (RailShape) possibleValue;
|
||||
+ if (isRailBlock) return !shape.isSlope();
|
||||
+ return !shape.isSlope() && shape != RailShape.NORTH_EAST && shape != RailShape.NORTH_WEST && shape != RailShape.SOUTH_EAST && shape != RailShape.SOUTH_WEST;
|
||||
+ }).toList();
|
||||
+ }
|
||||
+ return state.setValue(property, ShearsItem.getRelative(possibleValues, state.getValue(property), inverse)); // CraftBukkit - decompile error
|
||||
+ }
|
||||
+
|
||||
+ private static <T> T getRelative(Iterable<T> elements, T current, boolean inverse) {
|
||||
+ return inverse ? Util.findPreviousInIterable(elements, current) : Util.findNextInIterable(elements, current);
|
||||
+ }
|
||||
+
|
||||
+ private static void message(Player player, Component message) {
|
||||
+ ((ServerPlayer) player).sendSystemMessage(message, true);
|
||||
+ }
|
||||
+
|
||||
+ private static <T extends Comparable<T>> String getNameHelper(BlockState state, Property<T> property) {
|
||||
+ return property.getName(state.getValue(property));
|
||||
+ }
|
||||
+ // Leaves end - shears wrench
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 3 Oct 2025 19:43:36 +0800
|
||||
Subject: [PATCH] Modify merge ItemEntity logic
|
||||
|
||||
Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius,
|
||||
when the merge radius is large and stacks containing many items get stuck in an unexpected position,
|
||||
individual items may never reach their destination.
|
||||
This configuration option is added to fix this behavior.
|
||||
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index aed1641b4e09384d40da1ac6e66c1641ca34b063..44b06b1585e7630fa17d8dfb01f737b14efebcbc 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -287,7 +287,7 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
|
||||
ItemStack thisItemStack = this.getItem();
|
||||
ItemStack otherItemStack = other.getItem();
|
||||
if (Objects.equals(this.target, other.target) && areMergable(thisItemStack, otherItemStack)) {
|
||||
- if (otherItemStack.getCount() < thisItemStack.getCount()) {
|
||||
+ if (fun.bm.lophine.config.modules.misc.ItemEntityConfig.followTickSequenceMerge || otherItemStack.getCount() < thisItemStack.getCount()) { // Lophine - add follow Tick Sequence Merge, see Paper#13073
|
||||
merge(this, thisItemStack, other, otherItemStack);
|
||||
} else {
|
||||
merge(other, otherItemStack, this, thisItemStack);
|
||||
@@ -1,86 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 28 Jul 2025 01:06:40 +0800
|
||||
Subject: [PATCH] Leaves: Vanilla hopper
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/2c9f83c7b99178851edf5608b37b8c2adddd93cd/leaves-server/minecraft-patches/features/0095-Vanilla-hopper.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 8ba900fda7cce45679cde2b8b3272654129135ca..9d7ec9f4f18ed263540ccddf16c6c1a92d3477a4 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -280,36 +280,49 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
ItemStack movedItem = origItemStack;
|
||||
final int originalItemCount = origItemStack.getCount();
|
||||
final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount);
|
||||
- container.setChanged(); // original logic always marks source inv as changed even if no move happens.
|
||||
- movedItem.setCount(movedItemCount);
|
||||
|
||||
- if (!worldData.skipPullModeEventFire) { // Folia - region threading
|
||||
- movedItem = callPullMoveEvent(hopper, container, movedItem);
|
||||
- if (movedItem == null) { // cancelled
|
||||
+ // Leaves start - fix vanilla
|
||||
+ if (fun.bm.lophine.config.modules.misc.RedStoneConfig.vanillaHopper && movedItem.getCount() <= movedItemCount) {
|
||||
+ movedItem = origItemStack.copy();
|
||||
+ final ItemStack remainingItem = addItem(container, hopper, container.removeItem(i, movedItemCount), null);
|
||||
+ if (remainingItem.isEmpty()) {
|
||||
+ container.setChanged();
|
||||
+ return true;
|
||||
+ }
|
||||
+ container.setItem(i, movedItem);
|
||||
+ } else {
|
||||
+ container.setChanged(); // original logic always marks source inv as changed even if no move happens.
|
||||
+ movedItem.setCount(movedItemCount);
|
||||
+
|
||||
+ if (!worldData.skipPullModeEventFire) {
|
||||
+ movedItem = callPullMoveEvent(hopper, container, movedItem);
|
||||
+ if (movedItem == null) { // cancelled
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
+ // Drastically improve performance by returning true.
|
||||
+ // No plugin could have relied on the behavior of false as the other call
|
||||
+ // site for IMIE did not exhibit the same behavior
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
||||
+ final int remainingItemCount = remainingItem.getCount();
|
||||
+ if (remainingItemCount != movedItemCount) {
|
||||
+ origItemStack = origItemStack.copy(true);
|
||||
origItemStack.setCount(originalItemCount);
|
||||
- // Drastically improve performance by returning true.
|
||||
- // No plugin could have relied on the behavior of false as the other call
|
||||
- // site for IMIE did not exhibit the same behavior
|
||||
+ if (!origItemStack.isEmpty()) {
|
||||
+ origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
||||
+ }
|
||||
+
|
||||
+ IGNORE_TILE_UPDATES.set(true);
|
||||
+ container.setItem(i, origItemStack);
|
||||
+ IGNORE_TILE_UPDATES.set(false);
|
||||
+ container.setChanged();
|
||||
return true;
|
||||
}
|
||||
- }
|
||||
-
|
||||
- final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
||||
- final int remainingItemCount = remainingItem.getCount();
|
||||
- if (remainingItemCount != movedItemCount) {
|
||||
- origItemStack = origItemStack.copy(true);
|
||||
origItemStack.setCount(originalItemCount);
|
||||
- if (!origItemStack.isEmpty()) {
|
||||
- origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
||||
- }
|
||||
|
||||
- IGNORE_TILE_UPDATES.set(true); // Folia - region threading
|
||||
- container.setItem(i, origItemStack);
|
||||
- IGNORE_TILE_UPDATES.set(false); // Folia - region threading
|
||||
- container.setChanged();
|
||||
- return true;
|
||||
}
|
||||
- origItemStack.setCount(originalItemCount);
|
||||
+ // Leaves end - fix vanilla
|
||||
|
||||
if (level.paperConfig().hopper.cooldownWhenFull) {
|
||||
applyCooldown(hopper);
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 19 May 2025 00:42:17 +0800
|
||||
Subject: [PATCH] Old zombie reinforcement
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
index 0008aa0ca02fc4ea67b795b3f0a0e9656233ce89..2734ffc103ee4760d3521609fdd090ab99df675b 100644
|
||||
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
@@ -331,7 +331,7 @@ public class Zombie extends Monster {
|
||||
int x = Mth.floor(this.getX());
|
||||
int y = Mth.floor(this.getY());
|
||||
int z = Mth.floor(this.getZ());
|
||||
- EntityType<? extends Zombie> type = this.getType();
|
||||
+ EntityType<? extends Zombie> type = fun.bm.lophine.config.modules.function.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement
|
||||
Zombie reinforcement = type.create(level, EntitySpawnReason.REINFORCEMENT);
|
||||
if (reinforcement == null) {
|
||||
return true;
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 2 Jul 2026 18:49:40 +0800
|
||||
Subject: [PATCH] Old leader zombie health logic
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
index 2734ffc103ee4760d3521609fdd090ab99df675b..a99683d341f52139003dfa5190ee118d5b06f59f 100644
|
||||
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
|
||||
@@ -597,7 +597,7 @@ public class Zombie extends Monster {
|
||||
.addOrReplacePermanentModifier(
|
||||
new AttributeModifier(LEADER_ZOMBIE_BONUS_ID, this.random.nextDouble() * 3.0 + 1.0, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)
|
||||
);
|
||||
- if (spawnReason != EntitySpawnReason.CONVERSION && spawnReason != EntitySpawnReason.LOAD && spawnReason != EntitySpawnReason.DIMENSION_TRAVEL) {
|
||||
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.oldLeaderZombieHealth && spawnReason != EntitySpawnReason.CONVERSION && spawnReason != EntitySpawnReason.LOAD && spawnReason != EntitySpawnReason.DIMENSION_TRAVEL) { // Lophine - Configurable option to disable health boost for leader zombies
|
||||
this.setHealth(this.getMaxHealth());
|
||||
}
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 2 Aug 2025 12:40:53 +0800
|
||||
Subject: [PATCH] Leaves: Temporarily fix endermite spawn position
|
||||
|
||||
Should be removed when [https://github.com/PaperMC/Paper/pull/12912] merged
|
||||
|
||||
Co-authored by: Lumine1909 <133463833Lumine1909@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/4c4712d3304db7e977324b2bd6739f0c4433f80a/leaves-server/minecraft-patches/features/0140-Fix-endermite-spawn-position.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
index bded685ed1653e9a1e2d7d4a9c4f68da58a6b06e..7123e56d86db01073e8ea71ccce0f6308070c8ab 100644
|
||||
--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
+++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
|
||||
@@ -204,6 +204,9 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
|
||||
Vec3 vec3 = this.oldPosition();
|
||||
if (owner instanceof ServerPlayer serverPlayer) {
|
||||
if (serverPlayer.connection.isAcceptingMessages()) {
|
||||
+ // Paper start - fix endermite spawn position
|
||||
+ double x = serverPlayer.getX(), y = serverPlayer.getY(), z = serverPlayer.getZ();
|
||||
+ float yaw = serverPlayer.getYRot(), pitch = serverPlayer.getXRot();
|
||||
// CraftBukkit start
|
||||
ServerPlayer serverPlayer1 = serverPlayer.teleport(new TeleportTransition(serverLevel, vec3, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.ROTATION, Relative.DELTA), TeleportTransition.DO_NOTHING, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.ENDER_PEARL));
|
||||
if (serverPlayer1 == null) {
|
||||
@@ -214,7 +217,8 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
|
||||
if (this.random.nextFloat() < 0.05F && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
|
||||
Endermite endermite = EntityType.ENDERMITE.create(serverLevel, EntitySpawnReason.TRIGGERED);
|
||||
if (endermite != null) {
|
||||
- endermite.snapTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot());
|
||||
+ endermite.snapTo(x, y, z, yaw, pitch);
|
||||
+ // Paper end - fix endermite spawn position
|
||||
serverLevel.addFreshEntity(endermite, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.ENDER_PEARL);
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -5,36 +5,36 @@ Subject: [PATCH] Spawn invulnerable time
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 6b7c92fdf562dfa46eee8e8acbc82b02fc3226c5..144b2c9396b8162f9cce8b343d998907bf7fb5aa 100644
|
||||
index f7869f06ab29e4bbd003c807176345dec9e9e5ab..295be200cb0696bd2ae2b655f89d96dd7723a541 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -232,6 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -242,6 +242,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
private int lastSentFood = -99999999;
|
||||
private boolean lastFoodSaturationZero = true;
|
||||
public int lastSentExp = -99999999;
|
||||
+ private int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
+ protected int spawnInvulnerableTime = 60; // Lophine - spawn invulnerable time
|
||||
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
|
||||
public ParticleStatus particleStatus = ParticleStatus.ALL;
|
||||
private boolean canChatColor = true;
|
||||
@@ -925,6 +926,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.tickClientLoadTimeout();
|
||||
@@ -923,6 +924,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.connection.tickClientLoadTimeout();
|
||||
this.gameMode.tick();
|
||||
this.wardenSpawnTracker.tick();
|
||||
+ if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
|
||||
if (this.invulnerableTime > 0) {
|
||||
this.invulnerableTime--;
|
||||
}
|
||||
@@ -1435,6 +1437,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
if (this.isInvulnerableTo(level, damageSource)) {
|
||||
@@ -1559,6 +1561,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
if (this.isInvulnerableTo(level, source)) {
|
||||
return false;
|
||||
} else {
|
||||
+ // Lophine start - spawn invulnerable time
|
||||
+ if (fun.bm.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime) {
|
||||
+ if (this.spawnInvulnerableTime > 0 && !damageSource.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) {
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.spawnInvulnerableTime) {
|
||||
+ if (this.spawnInvulnerableTime > 0 && !source.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ // Lophine end - spawn invulnerable time
|
||||
Entity entity = damageSource.getEntity();
|
||||
Entity entity = source.getEntity();
|
||||
if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false.
|
||||
!(entity instanceof Player player && !this.canHarmPlayer(player))
|
||||
!(entity instanceof Player playerx && !this.canHarmPlayer(playerx))
|
||||
@@ -0,0 +1,466 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 26 Jul 2025 01:11:54 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/f3784ec0525069a37e9ab8921b196f5533edbd56/leaves-server/minecraft-patches/features/0118-Item-overstack-util.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
index 28aab52fb14e9086d81dd7a3fa32e7f12136d53a..1f033b970be82b0bdb4e51b6e1c5bb03170066ae 100644
|
||||
--- a/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
+++ b/net/minecraft/commands/arguments/item/ItemInput.java
|
||||
@@ -20,8 +20,10 @@ public record ItemInput(Holder<Item> item, DataComponentPatch components) {
|
||||
|
||||
public ItemStack createItemStack(final int count) throws CommandSyntaxException {
|
||||
ItemStack result = new ItemStack(this.item, count, this.components);
|
||||
- if (count > result.getMaxStackSize()) {
|
||||
- throw ERROR_STACK_TOO_BIG.create(this.item.getRegisteredName(), result.getMaxStackSize());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (count > org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(result)) {
|
||||
+ throw ERROR_STACK_TOO_BIG.create(this.item.getRegisteredName(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(result));
|
||||
+ // Leaves end - item over-stack util
|
||||
} else {
|
||||
DataResult<ItemStack> validationResult = ItemStack.validateStrict(result);
|
||||
return validationResult.getOrThrow(ERROR_MALFORMED_ITEM::create);
|
||||
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
|
||||
index c147a1acd4fd9f94c73bee69febf651ca00c28ce..f8004bf74edeabce871515fb73fa00f331941dca 100644
|
||||
--- a/net/minecraft/server/commands/GiveCommand.java
|
||||
+++ b/net/minecraft/server/commands/GiveCommand.java
|
||||
@@ -47,7 +47,7 @@ public class GiveCommand {
|
||||
|
||||
private static int giveItem(final CommandSourceStack source, final ItemInput input, final Collection<ServerPlayer> players, final int count) throws CommandSyntaxException {
|
||||
ItemStack prototypeItemStack = input.createItemStack(1);
|
||||
- int maxStackSize = prototypeItemStack.getMaxStackSize();
|
||||
+ int maxStackSize = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(prototypeItemStack); // Leaves - item over-stack util
|
||||
int maxAllowedCount = maxStackSize * 100;
|
||||
if (count > maxAllowedCount) {
|
||||
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", maxAllowedCount, prototypeItemStack.getDisplayName()));
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0b5f2060062a354bd6cafa8f53a5734dc83d062d..e15be199d690954d99d710de4046e721a943b3a9 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3229,7 +3229,7 @@ public class ServerGamePacketListenerImpl
|
||||
} else if (slot.mayPlace(cursor)) {
|
||||
if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
|
||||
int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1;
|
||||
- toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount());
|
||||
+ toPlace = Math.min(toPlace, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(clickedItem) - clickedItem.getCount()); // Leaves - item over-stack util
|
||||
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
|
||||
if (toPlace == 1) {
|
||||
action = InventoryAction.PLACE_ONE;
|
||||
@@ -3265,7 +3265,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
|
||||
if (clickedItem.getCount() >= 0) {
|
||||
- if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) {
|
||||
+ if (clickedItem.getCount() + cursor.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(cursor)) { // Leaves - item over-stack util
|
||||
// As of 1.5, this is result slots only
|
||||
action = InventoryAction.PICKUP_ALL;
|
||||
}
|
||||
@@ -3482,6 +3482,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.containerMenu.broadcastFullState();
|
||||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.broadcastCarriedItem(); // Leaves - item over-stack util - force send carried item
|
||||
}
|
||||
if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
@@ -3593,7 +3594,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
boolean validSlot = packet.slotNum() >= 1 && packet.slotNum() <= 45;
|
||||
- boolean validData = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
|
||||
+ boolean validData = itemStack.isEmpty() || itemStack.getCount() <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
if (drop || (validSlot && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
|
||||
// CraftBukkit start - Call click event
|
||||
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
|
||||
@@ -3635,6 +3636,7 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.hasOverstackingItem()) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - item over-stack util - force send carried item
|
||||
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else if (drop && validData) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
|
||||
index 54d99625cfec60530e8a3288871e6dc21e179b2d..2a1c1bd2e9c326b7298978cec1fe13112e670d33 100644
|
||||
--- a/net/minecraft/world/Container.java
|
||||
+++ b/net/minecraft/world/Container.java
|
||||
@@ -38,6 +38,12 @@ public interface Container extends Clearable, Iterable<ItemStack>, SlotProvider,
|
||||
return Math.min(this.getMaxStackSize(), itemStack.getMaxStackSize());
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ default int getMaxStackLeaves(final ItemStack stack) {
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(stack));
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
void setChanged();
|
||||
|
||||
boolean stillValid(Player player);
|
||||
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
|
||||
index 21f576bb39bfd78dca87606ba3a044db8e13e28e..049c6ab6472415479435f2caab0444c3cbd33902 100644
|
||||
--- a/net/minecraft/world/SimpleContainer.java
|
||||
+++ b/net/minecraft/world/SimpleContainer.java
|
||||
@@ -193,7 +193,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.items.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
|
||||
}
|
||||
|
||||
private void moveItemsBetweenStacks(final ItemStack sourceStack, final ItemStack targetStack) {
|
||||
- int maxCount = this.getMaxStackSize(targetStack);
|
||||
+ int maxCount = this.getMaxStackLeaves(targetStack); // Leaves - item over-stack util
|
||||
int diff = Math.min(sourceStack.getCount(), maxCount - targetStack.getCount());
|
||||
if (diff > 0) {
|
||||
targetStack.grow(diff);
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 44b06b1585e7630fa17d8dfb01f737b14efebcbc..679a941a2af886697fbfcbc7f21e5f4e0ec77dc3 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -280,10 +280,15 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish
|
||||
|
||||
private boolean isMergable() {
|
||||
ItemStack item = this.getItem();
|
||||
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
|
||||
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item); // Paper - Alternative item-despawn-rate // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
private void tryToMerge(final ItemEntity other) {
|
||||
+ // Leaves start - item over-stack util
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.tryStackItems(this, other)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
ItemStack thisItemStack = this.getItem();
|
||||
ItemStack otherItemStack = other.getItem();
|
||||
if (Objects.equals(this.target, other.target) && areMergable(thisItemStack, otherItemStack)) {
|
||||
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
|
||||
index f004911c438e6f89d6e079437e3f4104d6cbacbd..a248b1d11303237ebdf7cac4fa63865287d91a10 100644
|
||||
--- a/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -166,10 +166,12 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
private boolean hasRemainingSpaceForItem(final ItemStack slotItemStack, final ItemStack newItemStack) {
|
||||
+ // Leaves start - item over-stack util
|
||||
return !slotItemStack.isEmpty()
|
||||
- && slotItemStack.isStackable()
|
||||
- && slotItemStack.getCount() < this.getMaxStackSize(slotItemStack)
|
||||
+ && org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(slotItemStack)
|
||||
+ && slotItemStack.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(slotItemStack)
|
||||
&& ItemStack.isSameItemSameComponents(slotItemStack, newItemStack); // Paper - check if itemstack is stackable first
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
|
||||
// CraftBukkit start - Watch method above! :D
|
||||
@@ -182,7 +184,7 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
|
||||
- remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -191,7 +193,7 @@ public class Inventory implements Container, Nameable {
|
||||
|
||||
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
|
||||
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
|
||||
- remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount();
|
||||
+ remains -= (org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Leaves - item over-stack util
|
||||
}
|
||||
if (remains <= 0) {
|
||||
return itemStack.getCount();
|
||||
@@ -315,7 +317,7 @@ public class Inventory implements Container, Nameable {
|
||||
this.setItem(slot, itemStackInSlot);
|
||||
}
|
||||
|
||||
- int maxToAdd = this.getMaxStackSize(itemStackInSlot) - itemStackInSlot.getCount();
|
||||
+ int maxToAdd = this.getMaxStackLeaves(itemStackInSlot) - itemStackInSlot.getCount(); // Leaves - item over-stack util
|
||||
int toAdd = Math.min(count, maxToAdd);
|
||||
if (toAdd == 0) {
|
||||
return count;
|
||||
@@ -421,7 +423,7 @@ public class Inventory implements Container, Nameable {
|
||||
break;
|
||||
}
|
||||
|
||||
- int slotHasSpaceFor = itemStack.getMaxStackSize() - this.getItem(slot).getCount();
|
||||
+ int slotHasSpaceFor = org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) - this.getItem(slot).getCount(); // Leaves - item over-stack util
|
||||
if (this.add(slot, itemStack.split(slotHasSpaceFor)) && shouldSendSetSlotPacket && this.player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.connection.send(this.createInventoryUpdatePacket(slot));
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
index 1ace17d8fc7e7b8b4722a1889d49233c0ec55e20..d146f02338852810679a45bff932d9d68ee86d60 100644
|
||||
--- a/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
|
||||
@@ -36,7 +36,7 @@ public class StackedItemContents {
|
||||
}
|
||||
|
||||
public void accountStack(final ItemStack itemStack) {
|
||||
- this.accountStack(itemStack, itemStack.getMaxStackSize());
|
||||
+ this.accountStack(itemStack, org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public void accountStack(final ItemStack itemStack, final int maxCount) {
|
||||
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index 9c9a08752b54222e8ac8d9a38c7a28a775bd1164..42716cf2c864eba50628dc64c59ab29c1d51dc9b 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -161,7 +161,7 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
default void setChestVehicleItem(final int slot, final ItemStack itemStack) {
|
||||
this.unpackChestVehicleLootTable(null);
|
||||
this.getItemStacks().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
default @Nullable SlotAccess getChestVehicleSlot(final int slot) {
|
||||
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 4a177b4e714ba52cc18024d1233c9425afb93741..fa1f7dd22959632aaa54e72c8caf13ea072e7ca7 100644
|
||||
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -294,6 +294,14 @@ public abstract class AbstractContainerMenu {
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
+ // Leaves start - item over-stack util
|
||||
+ public void sendSingleSlot(final int slotIndex, final ItemStack item) {
|
||||
+ if (this.synchronizer != null) {
|
||||
+ this.synchronizer.sendSlotChange(this, slotIndex, item);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - item over-stack util
|
||||
+
|
||||
private void updateDataSlotListeners(final int id, final int currentValue) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, id, currentValue);
|
||||
@@ -450,7 +458,7 @@ public abstract class AbstractContainerMenu {
|
||||
&& (this.quickcraftType == QUICKCRAFT_TYPE_CLONE || carriedItemStack.getCount() >= this.quickcraftSlots.size())
|
||||
&& this.canDragTo(slot)) {
|
||||
int carry = slot.hasItem() ? slot.getItem().getCount() : 0;
|
||||
- int maxSize = Math.min(source.getMaxStackSize(), slot.getMaxStackSize(source));
|
||||
+ int maxSize = Math.min(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(source), slot.getMaxStackSize(source)); // Leaves - item over-stack util
|
||||
int newCount = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots.size(), this.quickcraftType, source) + carry, maxSize);
|
||||
remaining -= newCount - carry;
|
||||
// slot.setByPlayer(source.copyWithCount(newCount));
|
||||
@@ -558,7 +566,7 @@ public abstract class AbstractContainerMenu {
|
||||
slotx.setByPlayer(carried);
|
||||
}
|
||||
} else if (ItemStack.isSameItemSameComponents(clicked, carried)) {
|
||||
- Optional<ItemStack> newCarried = slotx.tryRemove(clicked.getCount(), carried.getMaxStackSize() - carried.getCount(), player);
|
||||
+ Optional<ItemStack> newCarried = slotx.tryRemove(clicked.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried) - carried.getCount(), player); // Leaves - item over-stack util
|
||||
newCarried.ifPresent(itemsTaken -> {
|
||||
carried.grow(itemsTaken.getCount());
|
||||
slotx.onTake(player, itemsTaken);
|
||||
@@ -620,7 +628,7 @@ public abstract class AbstractContainerMenu {
|
||||
Slot slotx = this.slots.get(slotIndex);
|
||||
if (slotx.hasItem()) {
|
||||
ItemStack item = slotx.getItem();
|
||||
- this.setCarried(item.copyWithCount(item.getMaxStackSize()));
|
||||
+ this.setCarried(item.copyWithCount(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(item))); // Leaves - item over-stack util
|
||||
}
|
||||
} else if (containerInput == ContainerInput.THROW && this.getCarried().isEmpty() && slotIndex >= 0) {
|
||||
Slot slotx = this.slots.get(slotIndex);
|
||||
@@ -655,15 +663,15 @@ public abstract class AbstractContainerMenu {
|
||||
int step = buttonNum == 0 ? 1 : -1;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
- for (int i = start; i >= 0 && i < this.slots.size() && carried.getCount() < carried.getMaxStackSize(); i += step) {
|
||||
+ for (int i = start; i >= 0 && i < this.slots.size() && carried.getCount() < org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried); i += step) { // Leaves - item over-stack util
|
||||
Slot target = this.slots.get(i);
|
||||
if (target.hasItem()
|
||||
&& canItemQuickReplace(target, carried, true)
|
||||
&& target.mayPickup(player)
|
||||
&& this.canTakeItemForPickAll(carried, target)) {
|
||||
ItemStack itemStack = target.getItem();
|
||||
- if (pass != 0 || itemStack.getCount() != itemStack.getMaxStackSize()) {
|
||||
- ItemStack removed = target.safeTake(itemStack.getCount(), carried.getMaxStackSize() - carried.getCount(), player);
|
||||
+ if (pass != 0 || itemStack.getCount() != org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)) { // Leaves - item over-stack util
|
||||
+ ItemStack removed = target.safeTake(itemStack.getCount(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(carried) - carried.getCount(), player); // Leaves - item over-stack util
|
||||
carried.grow(removed.getCount());
|
||||
}
|
||||
}
|
||||
@@ -770,7 +778,7 @@ public abstract class AbstractContainerMenu {
|
||||
destSlot = endSlot - 1;
|
||||
}
|
||||
|
||||
- if (itemStack.isStackable()) {
|
||||
+ if (org.leavesmc.leaves.util.ItemOverstackUtils.isStackable(itemStack)) { // Leaves - item over-stack util
|
||||
while (!itemStack.isEmpty() && (backwards ? destSlot >= startSlot : destSlot < endSlot)) {
|
||||
Slot slot = this.slots.get(destSlot);
|
||||
ItemStack target = slot.getItem();
|
||||
@@ -871,7 +879,7 @@ public abstract class AbstractContainerMenu {
|
||||
public static boolean canItemQuickReplace(final @Nullable Slot slot, final ItemStack itemStack, final boolean ignoreSize) {
|
||||
boolean slotIsEmpty = slot == null || !slot.hasItem();
|
||||
return !slotIsEmpty && ItemStack.isSameItemSameComponents(itemStack, slot.getItem())
|
||||
- ? slot.getItem().getCount() + (ignoreSize ? 0 : itemStack.getCount()) <= itemStack.getMaxStackSize()
|
||||
+ ? slot.getItem().getCount() + (ignoreSize ? 0 : itemStack.getCount()) <= org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack) // Leaves - item over-stack util
|
||||
: slotIsEmpty;
|
||||
}
|
||||
|
||||
@@ -879,7 +887,7 @@ public abstract class AbstractContainerMenu {
|
||||
return switch (quickCraftingType) {
|
||||
case 0 -> Mth.floor((float)itemStack.getCount() / quickCraftSlotsSize);
|
||||
case 1 -> 1;
|
||||
- case 2 -> itemStack.getMaxStackSize();
|
||||
+ case 2 -> org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack); // Leaves - item over-stack util
|
||||
default -> itemStack.getCount();
|
||||
};
|
||||
}
|
||||
@@ -902,7 +910,7 @@ public abstract class AbstractContainerMenu {
|
||||
for (int i = 0; i < container.getContainerSize(); i++) {
|
||||
ItemStack itemStack = container.getItem(i);
|
||||
if (!itemStack.isEmpty()) {
|
||||
- totalPercent += (float)itemStack.getCount() / container.getMaxStackSize(itemStack);
|
||||
+ totalPercent += org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackSignalStrength(container.getMaxStackSize(), itemStack); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
index e1b1a261a5f7a3702c1788daa38e7d367195382e..cb95fa63c585b1c3859bfd3e5d4d0e5dd84c7f0d 100644
|
||||
--- a/net/minecraft/world/inventory/MerchantContainer.java
|
||||
+++ b/net/minecraft/world/inventory/MerchantContainer.java
|
||||
@@ -108,7 +108,7 @@ public class MerchantContainer implements Container {
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.itemStacks.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
if (this.isPaymentSlot(slot)) {
|
||||
this.updateSellItem();
|
||||
}
|
||||
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
|
||||
index ee86a63c8d0d4c798ad09da87598d22c0e516840..57061d97bd368bfe934157293471fd546bb105ee 100644
|
||||
--- a/net/minecraft/world/inventory/Slot.java
|
||||
+++ b/net/minecraft/world/inventory/Slot.java
|
||||
@@ -75,7 +75,7 @@ public class Slot {
|
||||
}
|
||||
|
||||
public int getMaxStackSize(final ItemStack itemStack) {
|
||||
- return Math.min(this.getMaxStackSize(), itemStack.getMaxStackSize());
|
||||
+ return Math.min(this.getMaxStackSize(), org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
public @Nullable Identifier getNoItemIcon() {
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index 65d5c766eb9bfade4d8259bda418a7f0e413edbe..b052bc0107d93cd65a6c92914d6b3d02d6cc5ccb 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -160,7 +160,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
private int popTime;
|
||||
@Deprecated
|
||||
private @Nullable Holder<Item> item;
|
||||
- private PatchedDataComponentMap components;
|
||||
+ public PatchedDataComponentMap components; // Leaves - item over-stack util
|
||||
|
||||
public static DataResult<ItemStack> validateStrict(final ItemStack itemStack) {
|
||||
DataResult<?> result = validateComponents(itemStack.getComponents());
|
||||
@@ -185,7 +185,8 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
} else {
|
||||
Holder<Item> item = Item.STREAM_CODEC.decode(input);
|
||||
DataComponentPatch patch = patchCodec.decode(input);
|
||||
- return new ItemStack(item, count, patch);
|
||||
+ ItemStack stack = new ItemStack(item, count, patch);
|
||||
+ return org.leavesmc.leaves.util.ItemOverstackUtils.decodeMaxStackSize(stack); // Leaves - item over-stack util
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,17 +195,20 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
if (itemStack.isEmpty() || itemStack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
|
||||
output.writeVarInt(0);
|
||||
} else {
|
||||
- output.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count
|
||||
- Item.STREAM_CODEC.encode(output, itemStack.typeHolder());
|
||||
+ // Leaves start - item over-stack util
|
||||
+ final ItemStack encodedStack = org.leavesmc.leaves.util.ItemOverstackUtils.encodeMaxStackSize(itemStack.copy());
|
||||
+ output.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), encodedStack, encodedStack.getCount())); // Paper - potentially sanitize count
|
||||
+ Item.STREAM_CODEC.encode(output, encodedStack.typeHolder());
|
||||
// Paper start - adventure; conditionally render translatable components
|
||||
boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
|
||||
- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session
|
||||
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(encodedStack))) { // pass the itemstack as context to the obfuscation session
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
|
||||
- patchCodec.encode(output, itemStack.components.asPatch());
|
||||
+ patchCodec.encode(output, encodedStack.components.asPatch());
|
||||
} finally {
|
||||
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
|
||||
}
|
||||
// Paper end - adventure; conditionally render translatable components
|
||||
+ // Leaves end - item over-stack util
|
||||
}
|
||||
}
|
||||
};
|
||||
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
index 15ed625105539f402fb39275b292531fe388a7a0..2b97fd6af1c4956eb173b8c66c2a3efc8772a798 100644
|
||||
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||
@@ -202,7 +202,7 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||
Direction direction = blockState.getValue(ORIENTATION).front();
|
||||
Container into = HopperBlockEntity.getContainerAt(level, pos.relative(direction));
|
||||
ItemStack remaining = results.copy();
|
||||
- if (into != null && (into instanceof CrafterBlockEntity || results.getCount() > into.getMaxStackSize(results))) {
|
||||
+ if (into != null && (into instanceof CrafterBlockEntity || results.getCount() > into.getMaxStackLeaves(results))) { // Leaves - item over-stack util
|
||||
// CraftBukkit start - InventoryMoveItemEvent
|
||||
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(remaining);
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index 06d55281bb782cc064255c7b56acd6cd332b9085..d926be9a0c4954746032e3e96cf50a8cba5f26b3 100644
|
||||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -397,7 +397,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
ItemStack oldStack = this.items.get(slot);
|
||||
boolean same = !itemStack.isEmpty() && ItemStack.isSameItemSameComponents(oldStack, itemStack);
|
||||
this.items.set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
if (slot == 0 && !same && this.level instanceof ServerLevel serverLevel) {
|
||||
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
index 65ca3c97fdd60ebbdd366673c81c4375488f0cde..a7a13fb017a4c98db7639b8d672f3ad9d7814b7f 100644
|
||||
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
||||
@@ -134,7 +134,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
||||
@Override
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.getItems().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 75a8c007ba710aa6e77ba3ed9ae5f7868894629d..d036018ee64995ee754296014888ee70c0ea5ab3 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -155,7 +155,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public void setItem(final int slot, final ItemStack itemStack) {
|
||||
this.unpackLootTable(null);
|
||||
this.getItems().set(slot, itemStack);
|
||||
- itemStack.limitSize(this.getMaxStackSize(itemStack));
|
||||
+ itemStack.limitSize(this.getMaxStackLeaves(itemStack)); // Leaves - item over-stack util
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -670,9 +670,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (current.isEmpty()) {
|
||||
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
||||
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||
- if (!itemStack.isEmpty() && itemStack.getCount() > container.getMaxStackSize()) {
|
||||
+ if (!itemStack.isEmpty() && (itemStack.getCount() > container.getMaxStackSize() || itemStack.getCount() > itemStack.getMaxStackSize())) { // Leaves - item over-stack util
|
||||
leftover = itemStack; // Paper - Make hoppers respect inventory max stack size
|
||||
- itemStack = itemStack.split(container.getMaxStackSize());
|
||||
+ itemStack = itemStack.split(Math.min(container.getMaxStackSize(), itemStack.getMaxStackSize())); // Leaves - item over-stack util
|
||||
}
|
||||
// Spigot end
|
||||
IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading
|
||||
@@ -1,25 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sat, 26 Jul 2025 13:40:28 +0800
|
||||
Subject: [PATCH] Paper: Fix quick craft
|
||||
|
||||
Co-authored by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
As a part of : Paper (https://github.com/PaperMC/Paper/pull/11831/files#diff-3991edc9191addaab9f9701589f8fb4a05001c6f3c9ce1f51d22001f8de805ca)
|
||||
Licensed under: MIT (https://github.com/PaperMC/Paper/blob/main/licenses/MIT.md)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 5369a6597e48ed9f0d8f7f0b9685ce4950df4fe5..919628d93add71d9b30cae29587a0049cce6973d 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -4012,11 +4012,6 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
return null;
|
||||
} else {
|
||||
double d = this.getEyeY() - 0.3F;
|
||||
- // Paper start
|
||||
- final ItemStack tmp = stack.copy();
|
||||
- stack.setCount(0);
|
||||
- stack = tmp;
|
||||
- // Paper end
|
||||
ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), stack);
|
||||
itemEntity.setPickUpDelay(40);
|
||||
if (includeThrower) {
|
||||
@@ -0,0 +1,177 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 11 Apr 2025 16:53:57 +0800
|
||||
Subject: [PATCH] Leaves: Old raid behavior
|
||||
|
||||
Co-authored by: huanli233 <392352840@qq.com>
|
||||
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/bda7e406b995290234e33283a181e33467ceda38/leaves-server/minecraft-patches/features/0114-Old-raid-behavior.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
index f58b10c7dec0d2b7dc2b3d1198539b74d13038f3..0a838a2015526dde2cb8d9006a71610e0bf5e9dc 100644
|
||||
--- a/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
+++ b/net/minecraft/world/effect/BadOmenMobEffect.java
|
||||
@@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect {
|
||||
&& !player.isSpectator()
|
||||
&& level.getDifficulty() != Difficulty.PEACEFUL
|
||||
&& level.isVillage(player.blockPosition())) {
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ return level.getRaids().createOrExtendRaid(player, player.blockPosition()) == null;
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
Raid raid = level.getRaidAt(player.blockPosition());
|
||||
if (raid == null || raid.getRaidOmenLevel() < raid.getMaxRaidOmenLevel()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplification));
|
||||
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
|
||||
index 24cc4a15731edcb701596fe7051e188637457e37..5440dc0fb8bccabb65fd9681ab368ef5028e2ca9 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -268,7 +268,7 @@ public class Raid {
|
||||
}
|
||||
|
||||
public boolean absorbRaidOmen(final ServerPlayer player) {
|
||||
- MobEffectInstance effect = player.getEffect(MobEffects.RAID_OMEN);
|
||||
+ MobEffectInstance effect = player.getEffect(fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? MobEffects.BAD_OMEN : MobEffects.RAID_OMEN); // Leaves - old Raid Behavior
|
||||
if (effect == null) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -345,7 +345,13 @@ public class Raid {
|
||||
}
|
||||
|
||||
if (shouldTryToFindSpawnPos) {
|
||||
- this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ this.waveSpawnPos = this.preCalcRavagerSpawnLocation(level, this.raidCooldownTicks < 100 ? 1 : 0);
|
||||
+ } else {
|
||||
+ this.waveSpawnPos = this.getValidSpawnPos(level);
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
}
|
||||
|
||||
if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) {
|
||||
@@ -400,7 +406,14 @@ public class Raid {
|
||||
int attempt = 0;
|
||||
|
||||
while (this.shouldSpawnGroup()) {
|
||||
- BlockPos spawnPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ // Leaves Start - old FindSpawnPosition
|
||||
+ BlockPos spawnPos;
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior) {
|
||||
+ spawnPos = this.getRavagerSpawnLocation(level, attempt, 20);
|
||||
+ } else {
|
||||
+ spawnPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
|
||||
+ }
|
||||
+ // Leaves End - old FindSpawnPosition
|
||||
if (spawnPos != null) {
|
||||
this.started = true;
|
||||
this.spawnGroup(level, spawnPos);
|
||||
@@ -412,7 +425,7 @@ public class Raid {
|
||||
attempt++;
|
||||
}
|
||||
|
||||
- if (attempt > 5) {
|
||||
+ if (attempt > (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior ? 3 : 5)) { // Leaves - old FindSpawnPosition
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
|
||||
this.stop();
|
||||
break;
|
||||
@@ -716,7 +729,7 @@ public class Raid {
|
||||
int spawnX = this.center.getX() + Mth.floor(Mth.cos(angle) * 32.0F * howFar) + this.random.nextInt(3) * Mth.floor(howFar);
|
||||
int spawnZ = this.center.getZ() + Mth.floor(Mth.sin(angle) * 32.0F * howFar) + this.random.nextInt(3) * Mth.floor(howFar);
|
||||
int spawnY = level.getHeight(Heightmap.Types.WORLD_SURFACE, spawnX, spawnZ);
|
||||
- if (Mth.abs(spawnY - this.center.getY()) <= 96) {
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior || Mth.abs(spawnY - this.center.getY()) <= 96) { // Leaves - skippable
|
||||
spawnPos.set(spawnX, spawnY, spawnZ);
|
||||
if (!level.isVillage(spawnPos) || secondsRemaining <= 7) {
|
||||
int delta = 10;
|
||||
@@ -899,4 +912,42 @@ public class Raid {
|
||||
this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Leaves start - old FindSpawnPosition
|
||||
+ @Nullable
|
||||
+ private BlockPos getRavagerSpawnLocation(final ServerLevel serverWorld, final int proximity, final int tries) {
|
||||
+ int i = proximity == 0 ? 2 : 2 - proximity;
|
||||
+ BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||
+ net.minecraft.world.entity.SpawnPlacementType spawnLocation = net.minecraft.world.entity.SpawnPlacements.getPlacementType(EntityType.RAVAGER);
|
||||
+ for (int j = 0; j < tries; j++) {
|
||||
+ float f = serverWorld.getRandom().nextFloat() * (float) (Math.PI * 2);
|
||||
+ int k = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float) i + serverWorld.getRandom().nextInt(5));
|
||||
+ int l = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float) i + serverWorld.getRandom().nextInt(5));
|
||||
+ int m = serverWorld.getHeight(Heightmap.Types.WORLD_SURFACE, k, l);
|
||||
+ mutable.set(k, m, l);
|
||||
+ if (serverWorld.isVillage(mutable) && proximity < 2) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (serverWorld.hasChunksAt(mutable.getX() - 10, mutable.getZ() - 10, mutable.getX() + 10, mutable.getZ() + 10)
|
||||
+ && serverWorld.isPositionEntityTicking(mutable)
|
||||
+ && (spawnLocation.isSpawnPositionOk(serverWorld, mutable, EntityType.RAVAGER)
|
||||
+ || serverWorld.getBlockState(mutable.below()).is(net.minecraft.world.level.block.Blocks.SNOW)
|
||||
+ && serverWorld.getBlockState(mutable).isAir())
|
||||
+ ) {
|
||||
+ return mutable.immutable();
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<BlockPos> preCalcRavagerSpawnLocation(final ServerLevel serverWorld, final int proximity) {
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ BlockPos blockPos = this.getRavagerSpawnLocation(serverWorld, proximity, 1);
|
||||
+ if (blockPos != null) {
|
||||
+ return Optional.of(blockPos);
|
||||
+ }
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Leaves end - old FindSpawnPosition
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index bc2edc48ddefaab9022029f1a913a40b72e06024..1a51da9171c13711e106731c360051d183a40893 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -128,6 +128,42 @@ public abstract class Raider extends PatrollingMonster {
|
||||
|
||||
raidWhenKilled.removeFromRaid(serverLevel, this, false);
|
||||
}
|
||||
+
|
||||
+ // Leaves start - Revert raid changes
|
||||
+ Entity killerEntity = source.getEntity();
|
||||
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.oldRaidBehavior && !this.hasActiveRaid()) {
|
||||
+ ItemStack itemstack = this.getItemBySlot(net.minecraft.world.entity.EquipmentSlot.HEAD);
|
||||
+ net.minecraft.world.entity.player.Player entityhuman = null;
|
||||
+ if (killerEntity instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ } else if (killerEntity instanceof net.minecraft.world.entity.animal.wolf.Wolf wolf) {
|
||||
+ LivingEntity entityliving = wolf.getOwner();
|
||||
+ if (wolf.isTame() && entityliving instanceof net.minecraft.world.entity.player.Player player) {
|
||||
+ entityhuman = player;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (entityhuman != null && !itemstack.isEmpty() && this.isPatrolLeader()) {
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect = entityhuman.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ int amp = 1;
|
||||
+
|
||||
+ if (mobeffect != null) {
|
||||
+ amp += mobeffect.getAmplifier();
|
||||
+ entityhuman.removeEffectNoUpdate(net.minecraft.world.effect.MobEffects.BAD_OMEN);
|
||||
+ } else {
|
||||
+ --amp;
|
||||
+ }
|
||||
+
|
||||
+ amp = net.minecraft.util.Mth.clamp(amp, 0, 4);
|
||||
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, 120000, amp, false, false, true);
|
||||
+
|
||||
+ if (serverLevel.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.RAIDS)) {
|
||||
+ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit
|
||||
+ }
|
||||
+ this.setPatrolLeader(false);
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaves end - Revert raid changes
|
||||
}
|
||||
|
||||
super.die(source);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user