Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d74a32cb7 | |||
| 7da2307f4c | |||
| cdc69ecc09 | |||
| 7f0c8a2706 | |||
| 47bc8042d2 | |||
| 03849ba73c | |||
| ef3d1625b8 | |||
| c4acc049d8 | |||
| 3dc7b1edb7 | |||
| ab2992a2ef | |||
| 5622d49d49 | |||
| 7fdce6aedd | |||
| 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 |
@@ -1,7 +1,7 @@
|
|||||||
name: Bug反馈 Bug report
|
name: Bug反馈 Bug report
|
||||||
description:
|
description:
|
||||||
报告Bug,插件不兼容情况,以及其他相关问题。
|
报告Bug,插件不兼容情况,以及其他相关问题。
|
||||||
Report issues with plugin incompatbility or other behavior related issues.
|
Report issues with plugin incompatibility or other behavior related issues.
|
||||||
labels:
|
labels:
|
||||||
- bug
|
- bug
|
||||||
- pending
|
- pending
|
||||||
@@ -25,7 +25,7 @@ body:
|
|||||||
LophineMC服务端发行版本 LophineMC server release version (contains the git commit's hash)<br>
|
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.
|
通过执行`/version`命令将获取到的内容复制到这里。 Run `/version` on your server and paste the full, unmodified output here.
|
||||||
placeholder: >
|
placeholder: >
|
||||||
e.g. git-Lophine-"0635a89" (MC: 1.20.4)
|
e.g. git-Lophine-"fa1ab90" (MC: 1.21.8)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -41,7 +41,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: 观测到的实际行为 Observed/Actual behavior
|
label: 观测到的实际行为 Observed/Actual behavior
|
||||||
description: 你实际看到的。 What you actually saw.
|
description: 你实际看到的。 What you actually saw.
|
||||||
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
|
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -65,6 +65,20 @@ body:
|
|||||||
To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
|
To list plugins, run `/plugins`. For datapacks, run `/datapack list`.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
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
|
- type: textarea
|
||||||
id: other
|
id: other
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: othre
|
id: other
|
||||||
attributes:
|
attributes:
|
||||||
label: 其他 Other
|
label: 其他 Other
|
||||||
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
|
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
|
||||||
@@ -14,7 +14,7 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
default: ""
|
default: ""
|
||||||
force-push:
|
force-push:
|
||||||
description: "Force disable push to repo if you enter 2, push to repo if you enter 1, default push if not released else skip push repo"
|
description: "Force disable push to repo if you enter 2, force push to repo if you enter 1, default push if not released else skip push repo"
|
||||||
required: false
|
required: false
|
||||||
default: ""
|
default: ""
|
||||||
comments:
|
comments:
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
environment: default
|
environment: default
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Git Repository
|
- name: Checkout Git Repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set Up JDK
|
- name: Set Up JDK
|
||||||
uses: actions/setup-java@v5
|
uses: actions/setup-java@v5
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
|
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: ${{ env.project_id_b }} CI Artifacts
|
name: ${{ env.project_id_b }} CI Artifacts
|
||||||
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
|
path: lophine-server/build/libs/*-paperclip-*-mojmap.jar
|
||||||
@@ -84,8 +84,19 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "release_exists=${release_exists}" >> $GITHUB_ENV
|
echo "release_exists=${release_exists}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Check If Branch In Expectations
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_REF_NAME" == ver/* ]] || [[ "$GITHUB_REF_NAME" == exp/* ]] || [[ "$GITHUB_REF_NAME" == dev/* ]]; then
|
||||||
|
echo "Branch is in expected prefixes"
|
||||||
|
echo "unexpect=false" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "Branch is NOT in expected prefixes"
|
||||||
|
echo "unexpect=true" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Publish To Repo
|
- name: Publish To Repo
|
||||||
if: (( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-push == '2')) || inputs.force-push == '1') && false # do not push to any repo
|
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
|
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
|
||||||
env:
|
env:
|
||||||
@@ -93,13 +104,14 @@ jobs:
|
|||||||
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
|
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
|
||||||
|
|
||||||
- name: Create Release - Pre Process
|
- name: Create Release - Pre Process
|
||||||
if: ( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
|
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
|
||||||
run: |
|
run: |
|
||||||
if [ ${{ inputs.comments }} == "" ]; then
|
if [ "${{ inputs.comments }}" == "" ]; then
|
||||||
echo "No comments provided"
|
echo "No comments provided"
|
||||||
echo "flag_comment=true" >> $GITHUB_ENV
|
echo "flag_comment=false" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo "flag_comment=false" >> $GITHUB_ENV
|
echo "Comments provided: ${{ inputs.comments }}"
|
||||||
|
echo "flag_comment=true" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create Release - No Comment
|
- name: Create Release - No Comment
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: Qodana
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: # Specify your branches here
|
||||||
|
- ver/* # Stable branch
|
||||||
|
- exp/* # Experimental branch
|
||||||
|
- dev/* # Development Branch
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
qodana:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
checks: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
|
||||||
|
fetch-depth: 0 # a full history is required for pull request analysis
|
||||||
|
- name: 'Qodana Scan'
|
||||||
|
uses: JetBrains/qodana-action@latest
|
||||||
|
with:
|
||||||
|
pr-mode: false
|
||||||
|
env:
|
||||||
|
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_1658551725 }}
|
||||||
|
QODANA_ENDPOINT: 'https://qodana.cloud'
|
||||||
+3
-5
@@ -6,12 +6,10 @@ build
|
|||||||
|
|
||||||
/run
|
/run
|
||||||
|
|
||||||
/lightingluminol-server/build.gradle.kts
|
/lophine-server/build.gradle.kts
|
||||||
/lightingluminol-api/build.gradle.kts
|
/lophine-api/build.gradle.kts
|
||||||
/luminol-server/build.gradle.kts
|
/lophine-server/src/minecraft
|
||||||
/luminol-server/src/minecraft
|
|
||||||
/paper-server
|
/paper-server
|
||||||
/luminol-api/build.gradle.kts
|
|
||||||
/paper-api
|
/paper-api
|
||||||
/paper-api-generator
|
/paper-api-generator
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ dependencies {
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.earthme.luminol</groupId>
|
<groupId>fun.bm.lophine</groupId>
|
||||||
<artifactId>luminol-api</artifactId>
|
<artifactId>luminol-api</artifactId>
|
||||||
<version>$VERSION</version>
|
<version>$VERSION</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
+2
-2
@@ -62,7 +62,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("me.earthme.luminol:luminol-api:$VERSION")
|
compileOnly("fun.bm.lophine:lophine-api:$VERSION")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ dependencies {
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.earthme.luminol</groupId>
|
<groupId>fun.bm.lophine</groupId>
|
||||||
<artifactId>luminol-api</artifactId>
|
<artifactId>luminol-api</artifactId>
|
||||||
<version>$VERSION</version>
|
<version>$VERSION</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java // TODO java launcher tasks
|
java // TODO java launcher tasks
|
||||||
id("moe.luminolmc.hyacinthusweight.patcher") version "+" // Automatically pulls the latest
|
id("moe.luminolmc.hyacinthusweight.patcher")
|
||||||
}
|
}
|
||||||
|
|
||||||
paperweight {
|
paperweight {
|
||||||
|
|||||||
@@ -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` 动作 |
|
||||||
+3
-1
@@ -1,10 +1,12 @@
|
|||||||
group=fun.bm.lophine
|
group=fun.bm.lophine
|
||||||
version=1.21.8-R0.1-SNAPSHOT
|
version=1.21.8-R0.1-SNAPSHOT
|
||||||
mcVersion=1.21.8
|
mcVersion=1.21.8
|
||||||
|
clipVersion=3.0.15-20260413.051550-1
|
||||||
|
weightVersion=2.0.7
|
||||||
release=2
|
release=2
|
||||||
# 0 for skip release, 1 for pre-release, 2 for release
|
# 0 for skip release, 1 for pre-release, 2 for release
|
||||||
|
|
||||||
luminolRef=db9feeb2b0114cff9815b8b16ac3416846985693
|
luminolRef=170d047a69f8e4711651f475d6a795878651b1eb
|
||||||
|
|
||||||
org.gradle.configuration-cache=true
|
org.gradle.configuration-cache=true
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
+4
-1
@@ -1,8 +1,11 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
From: Bacteriawa <A3167717663@hotmail.com>
|
From: Bacteriawa <A3167717663@hotmail.com>
|
||||||
Date: Sat, 30 Aug 2025 16:51:26 +0800
|
Date: Sat, 30 Aug 2025 16:51:26 +0800
|
||||||
Subject: [PATCH] Add fakeplayer api
|
Subject: [PATCH] Leaves: Add fakeplayer api
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
|
||||||
index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113c1296d26 100644
|
index 85b778980e762835ac278528087e91b2e3effb43..89f00f4b6ff64305fa44ebb71f22a113c1296d26 100644
|
||||||
@@ -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 89f00f4b6ff64305fa44ebb71f22a113c1296d26..e9d20fe8b88aa63fb62effd430b5e22c8dbe1307 100644
|
||||||
|
--- a/src/main/java/org/bukkit/Bukkit.java
|
||||||
|
+++ b/src/main/java/org/bukkit/Bukkit.java
|
||||||
|
@@ -3063,4 +3063,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 c7ae463fb166750bbd0638a2ccf81753b293a381..4caadc8f9b328d978ece84c1480e32f24868531f 100644
|
||||||
|
--- a/src/main/java/org/bukkit/Server.java
|
||||||
|
+++ b/src/main/java/org/bukkit/Server.java
|
||||||
|
@@ -2762,4 +2762,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,43 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
*
|
||||||
|
* Leaves is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Leaves is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.leavesmc.leaves.entity.photographer;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface Photographer extends Player {
|
||||||
|
|
||||||
|
@NotNull String getId();
|
||||||
|
|
||||||
|
void setRecordFile(@NotNull File file);
|
||||||
|
|
||||||
|
void stopRecording();
|
||||||
|
|
||||||
|
void stopRecording(boolean async);
|
||||||
|
|
||||||
|
void stopRecording(boolean async, boolean save);
|
||||||
|
|
||||||
|
void pauseRecording();
|
||||||
|
|
||||||
|
void resumeRecording();
|
||||||
|
|
||||||
|
void setFollowPlayer(@Nullable Player player);
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
*
|
||||||
|
* Leaves is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Leaves is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.leavesmc.leaves.entity.photographer;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.leavesmc.leaves.replay.BukkitRecorderOption;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface PhotographerManager {
|
||||||
|
@Nullable Photographer getPhotographer(@NotNull UUID uuid);
|
||||||
|
|
||||||
|
@Nullable Photographer getPhotographer(@NotNull String id);
|
||||||
|
|
||||||
|
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location);
|
||||||
|
|
||||||
|
@Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption);
|
||||||
|
|
||||||
|
void removePhotographer(@NotNull String id);
|
||||||
|
|
||||||
|
void removePhotographer(@NotNull UUID uuid);
|
||||||
|
|
||||||
|
void removeAllPhotographers();
|
||||||
|
|
||||||
|
Collection<Photographer> getPhotographers();
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
*
|
||||||
|
* Leaves is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Leaves is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.leavesmc.leaves.replay;
|
||||||
|
|
||||||
|
public class BukkitRecorderOption {
|
||||||
|
|
||||||
|
// public int recordDistance = -1;
|
||||||
|
public String serverName = "Lophine"; // Lophine - rebrand to Lophine to avoid confusion
|
||||||
|
public BukkitRecordWeather forceWeather = BukkitRecordWeather.NULL;
|
||||||
|
public int forceDayTime = -1;
|
||||||
|
public boolean ignoreChat = false;
|
||||||
|
// public boolean ignoreItem = false;
|
||||||
|
|
||||||
|
public enum BukkitRecordWeather {
|
||||||
|
CLEAR,
|
||||||
|
RAIN,
|
||||||
|
THUNDER,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,12 +42,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
||||||
@@ -174,7 +_,7 @@
|
@@ -174,7 +_,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
- implementation(project(":luminol-api")) // Luminol
|
- implementation(project(":luminol-api")) // Luminol
|
||||||
+ implementation(project(":lophine-api")) // Lophine
|
+ implementation(project(":lophine-api")) // Lophine
|
||||||
|
+ implementation("net.objecthunter:exp4j:0.4.8") // Lophine
|
||||||
// Luminol start - Dependenices insert
|
// Luminol start - Dependenices insert
|
||||||
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
|
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
|
||||||
implementation("com.github.luben:zstd-jni:1.5.4-1")
|
implementation("com.github.luben:zstd-jni:1.5.4-1")
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ 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
|
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
index d8066afd5f3f2ea9a5dff87d853562e22268785c..f8b2364fa162a41304a99a4993354e33528ab801 100644
|
index 0bebc2cc87fb9c1c526e4de4f3bc157552307a72..cb1657939b86c039fcfe6403d3f202c2c5879e88 100644
|
||||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
@@ -21,6 +21,7 @@ public class ConfigManager {
|
@@ -23,6 +23,7 @@ public class ConfigManager {
|
||||||
|
|
||||||
public static void initConfigs() {
|
public static void initConfigs() {
|
||||||
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
|
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Subject: [PATCH] Transformed Configs
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||||
index ba360d57fd9ee2363c73863bc01b6592e59be4e5..86e6cc4c024ece5f45fb53b4cd341b1df2e8f0c7 100644
|
index 4051384e82dba0416838c3c9889a6e368367b601..a5535b479cdcca870d0c8be6ed6fbcb32f266ac2 100644
|
||||||
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||||
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||||
@@ -11,6 +11,7 @@ public class CommandConfig implements IConfigModule {
|
@@ -11,6 +11,7 @@ public class CommandConfig implements IConfigModule {
|
||||||
@@ -15,7 +15,7 @@ index ba360d57fd9ee2363c73863bc01b6592e59be4e5..86e6cc4c024ece5f45fb53b4cd341b1d
|
|||||||
+ @TransformedConfig(name = "command_block_enabled", directory = {"experiment", "command"}, originInstance = "lophine")
|
+ @TransformedConfig(name = "command_block_enabled", directory = {"experiment", "command"}, originInstance = "lophine")
|
||||||
@TransformedConfig(name = "enabled", directory = {"experiment", "force_enable_command_block_command_execution"})
|
@TransformedConfig(name = "enabled", directory = {"experiment", "force_enable_command_block_command_execution"})
|
||||||
@ConfigInfo(name = "enable_command_block", comments = """
|
@ConfigInfo(name = "enable_command_block", comments = """
|
||||||
Force to enable command blocks.
|
Force to enable command blocks.
|
||||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
|
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
|
||||||
index 35e6014f04093050a9a62b895b43e5c5d8c6a28e..11abfb884f972fd73ca4c13a6e309de1bcd23fd5 100644
|
index 35e6014f04093050a9a62b895b43e5c5d8c6a28e..11abfb884f972fd73ca4c13a6e309de1bcd23fd5 100644
|
||||||
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
|
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/PaperPacketLimiterConfig.java
|
||||||
|
|||||||
@@ -8,180 +8,69 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/d93e9766d3797d130
|
|||||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||||
index 3a6314ed7f62c6473ce9ddc9deeee2a32b9d2893..23a0f8100eb3162331161635e8051981c4e34aed 100644
|
index 112dc08eb62c4c50fb4859f51a366cedf027ca00..b5f661fd20b382725ad117c56ce2c94ded32b1b7 100644
|
||||||
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||||
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||||
@@ -17,12 +17,173 @@
|
@@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.leavesmc.leaves.util;
|
package org.leavesmc.leaves.util;
|
||||||
|
|
||||||
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
|
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
|
||||||
+import net.minecraft.core.component.DataComponents;
|
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||||
+import net.minecraft.nbt.CompoundTag;
|
import io.papermc.paper.datacomponent.item.ItemEnchantments;
|
||||||
+import net.minecraft.world.entity.item.ItemEntity;
|
import net.minecraft.core.component.DataComponents;
|
||||||
+import net.minecraft.world.item.BlockItem;
|
@@ -135,9 +136,9 @@ public class ItemOverstackUtils {
|
||||||
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 the used part is retained
|
private static class ShulkerBox implements ItemUtil {
|
||||||
public class ItemOverstackUtils {
|
public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
||||||
+ private static final List<ItemUtil> overstackUtils = List.of(
|
- /*if (LeavesConfig.modify.shulkerBox.sameNbtStackable) {
|
||||||
+ new ShulkerBox()
|
|
||||||
+ );
|
|
||||||
+
|
|
||||||
+ public static int getItemStackMaxCount(ItemStack stack) {
|
|
||||||
+ int size;
|
|
||||||
+ for (ItemUtil util : overstackUtils) {
|
|
||||||
+ if ((size = util.getMaxServerStackCount(stack)) != -1) {
|
|
||||||
+ return size;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return stack.getMaxStackSize();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static int getNetworkMaxCount(ItemStack stack) {
|
|
||||||
+ int size;
|
|
||||||
+ for (ItemUtil util : overstackUtils) {
|
|
||||||
+ if ((size = util.getMaxClientStackCount(stack)) != -1) {
|
|
||||||
+ return size;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return stack.getMaxStackSize();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
|
||||||
+ for (ItemUtil util : overstackUtils) {
|
|
||||||
+ if (util.tryStackItems(self, other)) {
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static boolean hasOverstackingItem() {
|
|
||||||
+ return overstackUtils.stream().anyMatch(ItemUtil::isEnabled);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static int getItemStackMaxCountReal(ItemStack stack) {
|
|
||||||
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
|
|
||||||
+ return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
|
|
||||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
|
||||||
+ int modifiedMaxStackSize = getNetworkMaxCount(itemStack);
|
|
||||||
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
|
|
||||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
|
|
||||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
|
||||||
+ nbt.putInt("Leaves.RealStackSize", realMaxStackSize);
|
|
||||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
|
||||||
+ }
|
|
||||||
+ return itemStack;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) {
|
|
||||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
|
||||||
+ if (itemStack.getMaxStackSize() != realMaxStackSize) {
|
|
||||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize);
|
|
||||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
|
||||||
+ nbt.remove("Leaves.RealStackSize");
|
|
||||||
+ if (nbt.isEmpty()) {
|
|
||||||
+ itemStack.remove(DataComponents.CUSTOM_DATA);
|
|
||||||
+ } else {
|
|
||||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return itemStack;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
public static float getItemStackSignalStrength(int maxStackSize, ItemStack itemStack) {
|
|
||||||
float result = (float) itemStack.getCount() / Math.min(maxStackSize, itemStack.getMaxStackSize());
|
|
||||||
return Math.clamp(result, 0f, 1f);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ public static boolean isStackable(ItemStack itemStack) {
|
|
||||||
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ private interface ItemUtil {
|
|
||||||
+ boolean isEnabled();
|
|
||||||
+
|
|
||||||
+ boolean tryStackItems(ItemEntity self, ItemEntity other);
|
|
||||||
+
|
|
||||||
+ // number -> modified count, -1 -> I don't care
|
|
||||||
+ int getMaxServerStackCount(ItemStack stack);
|
|
||||||
+
|
|
||||||
+ // number -> modified count, -1 -> I don't care
|
|
||||||
+ default int getMaxClientStackCount(ItemStack stack) {
|
|
||||||
+ return getMaxServerStackCount(stack);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private static class ShulkerBox implements ItemUtil {
|
|
||||||
+ public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
|
||||||
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
|
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
|
||||||
+ return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||||
|
- }*/ // Luminol
|
||||||
+ }
|
+ }
|
||||||
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||||
+ }
|
}
|
||||||
+
|
|
||||||
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
|
@@ -147,16 +148,15 @@ public class ItemOverstackUtils {
|
||||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
|
|
||||||
+ }
|
@Override
|
||||||
+
|
public boolean isEnabled() {
|
||||||
+ @Override
|
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes > 1; // Luminol
|
||||||
+ public boolean isEnabled() {
|
- return false; // Luminol
|
||||||
+ return ContainerExpansionConfig.shulkerCount > 1;
|
+ return ContainerExpansionConfig.shulkerCount > 1;
|
||||||
+ }
|
}
|
||||||
+
|
|
||||||
+ @Override
|
@Override
|
||||||
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||||
+ ItemStack selfStack = self.getItem();
|
ItemStack selfStack = self.getItem();
|
||||||
+ if (!isEnabled() ||
|
if (!isEnabled() ||
|
||||||
|
- !(selfStack.getItem() instanceof net.minecraft.world.item.BlockItem blockItem) ||
|
||||||
|
- !(blockItem.getBlock() instanceof net.minecraft.world.level.block.ShulkerBoxBlock)
|
||||||
+ !(selfStack.getItem() instanceof BlockItem blockItem) ||
|
+ !(selfStack.getItem() instanceof BlockItem blockItem) ||
|
||||||
+ !(blockItem.getBlock() instanceof ShulkerBoxBlock)
|
+ !(blockItem.getBlock() instanceof ShulkerBoxBlock)
|
||||||
+ ) {
|
) {
|
||||||
+ return false;
|
return false;
|
||||||
+ }
|
}
|
||||||
+
|
@@ -164,8 +164,8 @@ public class ItemOverstackUtils {
|
||||||
+ ItemStack otherStack = other.getItem();
|
ItemStack otherStack = other.getItem();
|
||||||
+ if (selfStack.getItem() == otherStack.getItem()
|
if (selfStack.getItem() == otherStack.getItem()
|
||||||
+ && shulkerBoxCheck(selfStack, otherStack)
|
&& shulkerBoxCheck(selfStack, otherStack)
|
||||||
|
- && selfStack.getCount() != /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/ 1) { // Luminol
|
||||||
|
- int amount = Math.min(otherStack.getCount(), /*org.leavesmc.leaves.LeavesConfig.modify.shulkerBox.stackableShulkerBoxes*/1 - selfStack.getCount()); // Luminol
|
||||||
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
|
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
|
||||||
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
|
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
|
||||||
+
|
|
||||||
+ selfStack.grow(amount);
|
selfStack.grow(amount);
|
||||||
+ self.setItem(selfStack);
|
self.setItem(selfStack);
|
||||||
+
|
@@ -187,9 +187,8 @@ public class ItemOverstackUtils {
|
||||||
+ self.pickupDelay = Math.max(other.pickupDelay, self.pickupDelay);
|
@Override
|
||||||
+ self.age = Math.min(other.getAge(), self.age);
|
public int getMaxServerStackCount(ItemStack stack) {
|
||||||
+
|
if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
|
||||||
+ otherStack.shrink(amount);
|
- bi.getBlock() instanceof ShulkerBoxBlock && (/*LeavesConfig.modify.shulkerBox.sameNbtStackable ||*/ shulkerBoxNoItem(stack))) { // Luminol
|
||||||
+ if (otherStack.isEmpty()) {
|
- // return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes; // Luminol
|
||||||
+ other.discard();
|
- return 1; // Luminol
|
||||||
+ } else {
|
|
||||||
+ other.setItem(otherStack);
|
|
||||||
+ }
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ @Override
|
|
||||||
+ public int getMaxServerStackCount(ItemStack stack) {
|
|
||||||
+ if (isEnabled() && stack.getItem() instanceof BlockItem bi &&
|
|
||||||
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
||||||
+ return ContainerExpansionConfig.shulkerCount;
|
+ return ContainerExpansionConfig.shulkerCount;
|
||||||
+ }
|
}
|
||||||
+ return -1;
|
return -1;
|
||||||
+ }
|
}
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 22 Apr 2026 00:51:19 +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 cb1657939b86c039fcfe6403d3f202c2c5879e88..3ba4faad544d2cf05b129a8d6142fc99a284299b 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
|
@@ -24,6 +24,13 @@ public class ConfigManager {
|
||||||
|
public static void initConfigs() {
|
||||||
|
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
|
||||||
|
configfiles.put("lophine", ConfigsInstance.of("lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
|
||||||
|
+ configfiles.put("lophine_carpet", ConfigsInstance.of(
|
||||||
|
+ new java.io.File("lophine_config"),
|
||||||
|
+ "lophine_carpet",
|
||||||
|
+ "lophine_carpet_config.toml",
|
||||||
|
+ "lophinecarpetconfig",
|
||||||
|
+ "fun.bm.lophine.carpet.config.modules"
|
||||||
|
+ )); // add lophine carpet config
|
||||||
|
preLoad();
|
||||||
|
}
|
||||||
|
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 22 Apr 2026 01:30:16 +0800
|
||||||
|
Subject: [PATCH] Luminol - 1.21.11: config system update
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/me/earthme/luminol/commands/bar/sub/ConfigEditCommand.java b/src/main/java/me/earthme/luminol/commands/bar/sub/ConfigEditCommand.java
|
||||||
|
index aad55088cb1ea2066f7f609b7d600e5ec0e68b8a..865f2ee6e4e63034a240c06b517c084a854141ed 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/commands/bar/sub/ConfigEditCommand.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/commands/bar/sub/ConfigEditCommand.java
|
||||||
|
@@ -57,7 +57,7 @@ public class ConfigEditCommand extends LiteralNode {
|
||||||
|
.text("Bar type with " + bar_name + " was already " + (value ? "enabled" : "disabled") + "!")
|
||||||
|
.color(TextColor.color(255, 0, 0)));
|
||||||
|
} else {
|
||||||
|
- ConfigsInstance config = ConfigManager.configfiles.get("luminol");
|
||||||
|
+ ConfigsInstance config = ConfigManager.getConfigs("luminol");
|
||||||
|
if (config.setConfig(configPath, value)) {
|
||||||
|
config.reloadAsync(true).thenAccept(nullValue -> context.getSender().sendMessage(
|
||||||
|
Component
|
||||||
|
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
|
index 3ba4faad544d2cf05b129a8d6142fc99a284299b..60a73a29ed2a4e0587a7c90186f990189c7da872 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||||
|
@@ -6,15 +6,16 @@ import me.earthme.luminol.config.flags.TransformedConfig;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
-import java.util.HashSet;
|
||||||
|
-import java.util.Map;
|
||||||
|
-import java.util.Set;
|
||||||
|
+import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
+import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class ConfigManager {
|
||||||
|
- public static final Map<String, ConfigsInstance> configfiles = new ConcurrentHashMap<>();
|
||||||
|
- public static final Map<TransformedConfig, String[]> needTransformedConfigs = new ConcurrentHashMap<>();
|
||||||
|
+ private static boolean initialized = false;
|
||||||
|
+ private static final Map<String, ConfigsInstance> configfiles = new HashMap<>();
|
||||||
|
+ private static final Collection<Runnable> runnableBeforeFinalLoad = new ConcurrentLinkedQueue<>();
|
||||||
|
+ private static final Map<TransformedConfig, String[]> needTransformedConfigs = new ConcurrentHashMap<>();
|
||||||
|
// String[]:
|
||||||
|
// 0 -> origin key
|
||||||
|
// 1 -> target key
|
||||||
|
@@ -49,21 +50,34 @@ public class ConfigManager {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadConfigFiles() {
|
||||||
|
+ runTaskBeforeFinalLoad();
|
||||||
|
CompletableFuture<?>[] futures = configfiles.values().stream()
|
||||||
|
.map(config -> CompletableFuture.runAsync(config::finalizeLoadConfig))
|
||||||
|
.toArray(CompletableFuture[]::new);
|
||||||
|
CompletableFuture.allOf(futures).join();
|
||||||
|
CommandRegister.register(); // register command after config loaded to enable some command didn't depend on config files
|
||||||
|
+ initialized = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static void registerRunnableBeforeFinalLoad(Runnable runnable) {
|
||||||
|
+ if (initialized) return;
|
||||||
|
+ runnableBeforeFinalLoad.add(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerTransformedConfig(@NotNull String origin, @NotNull String target, @NotNull String originKey, @NotNull String targetKey, TransformedConfig transformedConfig) {
|
||||||
|
+ if (initialized) return;
|
||||||
|
needTransformedConfigs.put(transformedConfig, new String[]{origin, target, originKey, targetKey});
|
||||||
|
}
|
||||||
|
|
||||||
|
- private static ConfigsInstance getConfigs(String name) {
|
||||||
|
+ public static ConfigsInstance getConfigs(String name) {
|
||||||
|
return configfiles.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ private static void runTaskBeforeFinalLoad() {
|
||||||
|
+ runnableBeforeFinalLoad.forEach(Runnable::run);
|
||||||
|
+ runnableBeforeFinalLoad.clear();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
private static void acceptTransformedConfigs() {
|
||||||
|
Set<ConfigsInstance> toReload = new HashSet<>();
|
||||||
|
for (Map.Entry<TransformedConfig, String[]> entry : needTransformedConfigs.entrySet()) {
|
||||||
|
diff --git a/src/main/java/me/earthme/luminol/config/ConfigsInstance.java b/src/main/java/me/earthme/luminol/config/ConfigsInstance.java
|
||||||
|
index bd9ff74e482906701077f801c3f97bf5bd8f195b..55b01a36f45cf3534ee0b30ba27c9682b078ac1b 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/config/ConfigsInstance.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/config/ConfigsInstance.java
|
||||||
|
@@ -248,7 +248,8 @@ public class ConfigsInstance {
|
||||||
|
*/
|
||||||
|
private List<String> buildConfigCategoryPath(ConfigClassInfo configClassInfo) {
|
||||||
|
final List<String> category = new ArrayList<>();
|
||||||
|
- category.add(configClassInfo.category().getBaseKeyName());
|
||||||
|
+ String category0 = configClassInfo.category().getBaseKeyName();
|
||||||
|
+ if (category0 != null) category.add(category0);
|
||||||
|
category.addAll(List.of(configClassInfo.directory()));
|
||||||
|
category.add(configClassInfo.name());
|
||||||
|
return category;
|
||||||
|
@@ -311,6 +312,9 @@ public class ConfigsInstance {
|
||||||
|
// Handle existing configurations
|
||||||
|
handleExistingConfig(field, fullConfigKeyName, configInfo, doNotReload, keepComments);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // handle tasks need processed before config finalized
|
||||||
|
+ ConfigManager.registerRunnableBeforeFinalLoad(singleConfigModule::beforeFinalLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/src/main/java/me/earthme/luminol/config/IConfigModule.java b/src/main/java/me/earthme/luminol/config/IConfigModule.java
|
||||||
|
index c5fee207479c331575d49cf625164ac2f5362d4a..dc880ce0f1fcec0acc9706324eef9a4a6e16ee17 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/config/IConfigModule.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/config/IConfigModule.java
|
||||||
|
@@ -7,6 +7,9 @@ import org.jetbrains.annotations.Nullable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface IConfigModule {
|
||||||
|
+ default void beforeFinalLoad() {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
default void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/main/java/me/earthme/luminol/enums/EnumConfigCategory.java b/src/main/java/me/earthme/luminol/enums/EnumConfigCategory.java
|
||||||
|
index f79bf3dd37519c61ed0aa87b9b51c7ab7bc02d11..07e33c5e1f2dc9ce3fc18f48580b13f9aef6244a 100644
|
||||||
|
--- a/src/main/java/me/earthme/luminol/enums/EnumConfigCategory.java
|
||||||
|
+++ b/src/main/java/me/earthme/luminol/enums/EnumConfigCategory.java
|
||||||
|
@@ -7,7 +7,8 @@ public enum EnumConfigCategory {
|
||||||
|
FUNCTION("function"), // new functions
|
||||||
|
EXPERIMENT("experiment"), // experimental features
|
||||||
|
UNSUPPORTED("unsupported"), // features we do not want anyone to use
|
||||||
|
- REMOVED("removed"); // removed config
|
||||||
|
+ REMOVED("removed"), // removed config
|
||||||
|
+ ROOT(null);
|
||||||
|
|
||||||
|
private final String baseKeyName;
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
-60
@@ -1,60 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
|
||||||
Date: Mon, 7 Jul 2025 16:30:54 +0800
|
|
||||||
Subject: [PATCH] Add config to allow infinite trade
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
|
||||||
index 79242037e868a140513f032e74e8594c0c6ff41c..050e89c3e95c7c3ef7ad98f8ef03ab206241a7e2 100644
|
|
||||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
|
||||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
|
||||||
@@ -490,8 +490,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resendOffersToTradingPlayer() {
|
|
||||||
- MerchantOffers offers = this.getOffers();
|
|
||||||
+ // Lophine start - infinite trade
|
|
||||||
+ MerchantOffers offers = this.getOffers().copy();
|
|
||||||
Player tradingPlayer = this.getTradingPlayer();
|
|
||||||
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
|
|
||||||
+ for (MerchantOffer merchantOffer : offers) {
|
|
||||||
+ merchantOffer.maxUses = 524288;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - infinite trade
|
|
||||||
if (tradingPlayer != null && !offers.isEmpty()) {
|
|
||||||
tradingPlayer.sendMerchantOffers(
|
|
||||||
tradingPlayer.containerMenu.containerId,
|
|
||||||
diff --git a/net/minecraft/world/item/trading/Merchant.java b/net/minecraft/world/item/trading/Merchant.java
|
|
||||||
index 6e2fa442ddcd4ef3c4fe789b9ebac9dd409c9de7..0c7318a0ed214204f5493576c8a7b02fbe51c00b 100644
|
|
||||||
--- a/net/minecraft/world/item/trading/Merchant.java
|
|
||||||
+++ b/net/minecraft/world/item/trading/Merchant.java
|
|
||||||
@@ -42,7 +42,14 @@ public interface Merchant {
|
|
||||||
new SimpleMenuProvider((containerId, inventory, player1) -> new MerchantMenu(containerId, inventory, this), displayName)
|
|
||||||
);
|
|
||||||
if (optionalInt.isPresent()) {
|
|
||||||
- MerchantOffers offers = this.getOffers();
|
|
||||||
+ // Lophine start - infinite trade
|
|
||||||
+ MerchantOffers offers = this.getOffers().copy();
|
|
||||||
+ if (fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade) {
|
|
||||||
+ for (MerchantOffer merchantOffer : offers) {
|
|
||||||
+ merchantOffer.maxUses = 5242884;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - infinite trade
|
|
||||||
if (!offers.isEmpty()) {
|
|
||||||
player.sendMerchantOffers(optionalInt.getAsInt(), offers, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock());
|
|
||||||
}
|
|
||||||
diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java
|
|
||||||
index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..770f37d7158c7b4cec62783025f623a68c1f2457 100644
|
|
||||||
--- a/net/minecraft/world/item/trading/MerchantOffer.java
|
|
||||||
+++ b/net/minecraft/world/item/trading/MerchantOffer.java
|
|
||||||
@@ -196,7 +196,7 @@ public class MerchantOffer {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOutOfStock() {
|
|
||||||
- return this.uses >= this.maxUses;
|
|
||||||
+ return (this.uses >= this.maxUses && !fun.bm.lophine.config.modules.function.VillagerConfig.villagerInfiniteTrade); // Lophine - infinite trade
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToOutOfStock() {
|
|
||||||
+2
-2
@@ -18,7 +18,7 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1
|
|||||||
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
|
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
|
||||||
if (rangeY != -1) {
|
if (rangeY != -1) {
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index 34d802060e096c5acfbd9a66fab96c0e8c792fe1..47ef63061737f3efdb0ce7ec71a8d9c920385bb0 100644
|
index 38092dcc3dedc6c855e5598126be47f892223547..a8b6e89035579557b59a20ddbe9b32943e6b7164 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||||
@@ -30,7 +30,7 @@ index 34d802060e096c5acfbd9a66fab96c0e8c792fe1..47ef63061737f3efdb0ce7ec71a8d9c9
|
|||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
private static final int CURRENT_LEVEL = 2;
|
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
|
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
|
||||||
@@ -6480,4 +6480,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -6463,4 +6463,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
// Paper end - Expose entity id counter
|
// Paper end - Expose entity id counter
|
||||||
|
|
||||||
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
||||||
+2
-2
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable function command
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||||
index af895859057ca303177ec3c8a07cf7534e62cca6..e0e9fcf3224f55f2ef31c8afca3154a5992f761b 100644
|
index 11697e65a7f7871920ca7bad37de07f78a3da1f8..25ccbfa12d57d540195ecc16aa54a144f8ecc0e8 100644
|
||||||
--- a/net/minecraft/commands/Commands.java
|
--- a/net/minecraft/commands/Commands.java
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
@@ -206,7 +206,9 @@ public class Commands {
|
@@ -204,7 +204,9 @@ public class Commands {
|
||||||
FillCommand.register(this.dispatcher, context);
|
FillCommand.register(this.dispatcher, context);
|
||||||
FillBiomeCommand.register(this.dispatcher, context);
|
FillBiomeCommand.register(this.dispatcher, context);
|
||||||
ForceLoadCommand.register(this.dispatcher);
|
ForceLoadCommand.register(this.dispatcher);
|
||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
|
||||||
Date: Wed, 2 Jul 2025 23:36:25 +0800
|
|
||||||
Subject: [PATCH] Add config to enable datapack command
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
|
||||||
index e05f75b6bbd48d6fb7379926d68d5f8ed6014be9..af895859057ca303177ec3c8a07cf7534e62cca6 100644
|
|
||||||
--- a/net/minecraft/commands/Commands.java
|
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
|
||||||
@@ -192,7 +192,9 @@ public class Commands {
|
|
||||||
if(me.earthme.luminol.config.modules.experiment.CommandConfig.data) {
|
|
||||||
DataCommands.register(this.dispatcher); // Folia - region threading - TODO
|
|
||||||
}
|
|
||||||
- //DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
|
||||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.datapack) {
|
|
||||||
+ DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
|
||||||
+ }
|
|
||||||
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
|
|
||||||
DefaultGameModeCommands.register(this.dispatcher);
|
|
||||||
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
|
||||||
index 75027e73859c955a54034640f905cb5d91a6a2f4..b4b3ff86f7c4afb94fc4da5133746391a078a7fb 100644
|
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
|
||||||
@@ -2353,6 +2353,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
||||||
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
|
||||||
+ public void saveDatapacks(Collection<String> selectedIds) {
|
|
||||||
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
|
|
||||||
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
|
|
||||||
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
|
|
||||||
+ );
|
|
||||||
+ this.worldData.setDataConfiguration(worldDataConfiguration);
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
|
||||||
+
|
|
||||||
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
|
|
||||||
// Paper end - Add ServerResourcesReloadedEvent
|
|
||||||
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
|
|
||||||
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
|
|
||||||
index b540a3c3a02f7242578a63477e34b9063e86f1d2..9f0adf157872e1c68cd7752a24eacdc636e8d17a 100644
|
|
||||||
--- a/net/minecraft/server/commands/ReloadCommand.java
|
|
||||||
+++ b/net/minecraft/server/commands/ReloadCommand.java
|
|
||||||
@@ -16,6 +16,12 @@ public class ReloadCommand {
|
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
|
||||||
|
|
||||||
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
|
|
||||||
+ // Lophine start - region thread skip reload // TODO - add reload support
|
|
||||||
+ if (true) {
|
|
||||||
+ source.getServer().saveDatapacks(selectedIds);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - region thread skip reload // TODO - add reload support
|
|
||||||
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
|
|
||||||
LOGGER.warn("Failed to execute reload", throwable);
|
|
||||||
source.sendFailure(Component.translatable("commands.reload.failure"));
|
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Fri, 16 Jan 2026 02:34:43 +0800
|
||||||
|
Subject: [PATCH] Add config to enable save-all command
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
|
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..6deaeaf95a43e217f65d3e0764b844ff4573d4ca 100644
|
||||||
|
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
|
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
|
@@ -317,6 +317,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 bfb39cbf1ba58d02da7e35300eb95872747506e8..25e8f26f708b68bd90f57863e7833e6502d981e2 100644
|
||||||
|
--- a/io/papermc/paper/threadedregions/TickRegions.java
|
||||||
|
+++ b/io/papermc/paper/threadedregions/TickRegions.java
|
||||||
|
@@ -168,6 +168,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 25ccbfa12d57d540195ecc16aa54a144f8ecc0e8..c00e0e74cb4c820a5c8b3722ebc1ff56318dae02 100644
|
||||||
|
--- a/net/minecraft/commands/Commands.java
|
||||||
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
|
@@ -277,7 +277,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 75027e73859c955a54034640f905cb5d91a6a2f4..1fa4110b61e49ee9527b65ecafb96b0dcd2c8ce2 100644
|
||||||
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -1581,6 +1581,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
// Folia start - region threading
|
||||||
|
public void tickServer(long startTime, long scheduledEnd, long targetBuffer,
|
||||||
|
io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
|
||||||
|
+ // Lophine start - save-all fix
|
||||||
|
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
|
||||||
|
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - save-all fix
|
||||||
|
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||||
|
// Folia end - region threading
|
||||||
|
org.spigotmc.WatchdogThread.tick(); // Spigot
|
||||||
|
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
|
||||||
|
index 15e0fce7500dc2dc2a712bf61d1d5506fd8f317a..71f53f057527192f8f830c7d21bd72233479fe55 100644
|
||||||
|
--- a/net/minecraft/server/commands/SaveAllCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/SaveAllCommand.java
|
||||||
|
@@ -21,7 +21,9 @@ public class SaveAllCommand {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int saveAll(CommandSourceStack source, boolean flush) throws CommandSyntaxException {
|
||||||
|
- source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||||
|
+ // Lophine start - save all
|
||||||
|
+ fun.bm.lophine.utils.SaveAllUtil.preSaveAll(source, flush);
|
||||||
|
+/* source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
|
||||||
|
MinecraftServer server = source.getServer();
|
||||||
|
boolean flag = server.saveEverything(true, flush, true);
|
||||||
|
if (!flag) {
|
||||||
|
@@ -29,6 +31,12 @@ public class SaveAllCommand {
|
||||||
|
} else {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
|
||||||
|
return 1;
|
||||||
|
- }
|
||||||
|
+ }*/
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public static SimpleCommandExceptionType getErrorFailed() {
|
||||||
|
+ return ERROR_FAILED;
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - save all
|
||||||
|
}
|
||||||
+2
-2
@@ -5,10 +5,10 @@ Subject: [PATCH] Add config to enable scoreboard command
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||||
index e0e9fcf3224f55f2ef31c8afca3154a5992f761b..6633af3cff77bcd4bcc591c032d647b7a850dced 100644
|
index c00e0e74cb4c820a5c8b3722ebc1ff56318dae02..2be7e5de57f474a3600ea4990899c1955faa512e 100644
|
||||||
--- a/net/minecraft/commands/Commands.java
|
--- a/net/minecraft/commands/Commands.java
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
@@ -231,7 +231,11 @@ public class Commands {
|
@@ -229,7 +229,11 @@ public class Commands {
|
||||||
//RotateCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
//RotateCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||||
SayCommand.register(this.dispatcher);
|
SayCommand.register(this.dispatcher);
|
||||||
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
|
//ScheduleCommand.register(this.dispatcher); // Folia - region threading
|
||||||
+6
-6
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable tick command
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839621d73d7 100644
|
index 6deaeaf95a43e217f65d3e0764b844ff4573d4ca..1cefe9d83788dafc293aeb6d1b5e635211094b2a 100644
|
||||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
@@ -299,6 +299,11 @@ public final class RegionizedServer {
|
@@ -299,6 +299,11 @@ public final class RegionizedServer {
|
||||||
@@ -20,7 +20,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
|||||||
// expire invalid click command callbacks
|
// 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.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
|
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 {
|
@@ -324,6 +329,13 @@ public final class RegionizedServer {
|
||||||
this.globalTick(world, tickCount);
|
this.globalTick(world, tickCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839
|
|||||||
// tick connections
|
// tick connections
|
||||||
this.tickConnections();
|
this.tickConnections();
|
||||||
|
|
||||||
@@ -455,7 +467,7 @@ public final class RegionizedServer {
|
@@ -457,7 +469,7 @@ public final class RegionizedServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickTime(final ServerLevel world, final int tickCount) {
|
private void tickTime(final ServerLevel world, final int tickCount) {
|
||||||
@@ -97,10 +97,10 @@ index c485d5b3ba95f2a969bdf0dab9654ac284976f8d..b957585cf7cf7f845e20f59c7b355722
|
|||||||
this.scheduler.regionFailed(this, false, thr);
|
this.scheduler.regionFailed(this, false, thr);
|
||||||
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
|
// 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
|
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||||
index 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc 100644
|
index 2be7e5de57f474a3600ea4990899c1955faa512e..8d332f8e99ceb5a20b3b54bc327b024968719017 100644
|
||||||
--- a/net/minecraft/commands/Commands.java
|
--- a/net/minecraft/commands/Commands.java
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
@@ -251,7 +251,11 @@ public class Commands {
|
@@ -249,7 +249,11 @@ public class Commands {
|
||||||
TeleportCommand.register(this.dispatcher);
|
TeleportCommand.register(this.dispatcher);
|
||||||
TellRawCommand.register(this.dispatcher, context);
|
TellRawCommand.register(this.dispatcher, context);
|
||||||
//TestCommand.register(this.dispatcher, context); // Folia - region threading
|
//TestCommand.register(this.dispatcher, context); // Folia - region threading
|
||||||
@@ -114,7 +114,7 @@ index 6633af3cff77bcd4bcc591c032d647b7a850dced..dc5a558c72a5a7ab8a650262c6a1a2dc
|
|||||||
TitleCommand.register(this.dispatcher, context);
|
TitleCommand.register(this.dispatcher, context);
|
||||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index b4b3ff86f7c4afb94fc4da5133746391a078a7fb..b156b5c635f931a3d4abc0584591f90476d011a6 100644
|
index 1fa4110b61e49ee9527b65ecafb96b0dcd2c8ce2..df5ff1cc7b289c3f52723d4e7b418e79ae6c3082 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Mon, 7 Jul 2025 18:19:00 +0800
|
||||||
|
Subject: [PATCH] Add config to enable waypoint command & bar
|
||||||
|
|
||||||
|
use concurrent method to fix it (now, they are thread safe)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||||
|
index 8d332f8e99ceb5a20b3b54bc327b024968719017..d4357499cbfd0474dae3c66b4473b81367f284d1 100644
|
||||||
|
--- a/net/minecraft/commands/Commands.java
|
||||||
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
|
@@ -257,7 +257,11 @@ public class Commands {
|
||||||
|
TimeCommand.register(this.dispatcher);
|
||||||
|
TitleCommand.register(this.dispatcher, context);
|
||||||
|
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||||
|
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
||||||
|
+ // Lophine start - unsafe waypoint bar
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) {
|
||||||
|
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - unsafe waypoint bar
|
||||||
|
WeatherCommand.register(this.dispatcher);
|
||||||
|
WorldBorderCommand.register(this.dispatcher);
|
||||||
|
if (JvmProfiler.INSTANCE.isAvailable()) {
|
||||||
|
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
|
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..65a4956ba2f0e38da7ae4f8cd7ed6e4b02c015a9 100644
|
||||||
|
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
|
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
|
@@ -16,22 +16,31 @@ import net.minecraft.world.waypoints.WaypointManager;
|
||||||
|
import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||||
|
|
||||||
|
public class ServerWaypointManager implements WaypointManager<WaypointTransmitter> {
|
||||||
|
- private final Set<WaypointTransmitter> waypoints = new HashSet<>();
|
||||||
|
- private final Set<ServerPlayer> players = new HashSet<>();
|
||||||
|
- private final Table<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = HashBasedTable.create();
|
||||||
|
+ private final Set<WaypointTransmitter> waypoints = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent
|
||||||
|
+ private final Set<ServerPlayer> players = new java.util.concurrent.CopyOnWriteArraySet<>(); // Lophine - concurrent
|
||||||
|
+ private final fun.bm.lophine.utils.concurrent.AbstractConcurrentTable<ServerPlayer, WaypointTransmitter, WaypointTransmitter.Connection> connections = fun.bm.lophine.config.modules.optimizations.WayPointOptimizedTableConfig.optimizedTable ? new fun.bm.lophine.utils.concurrent.OptimizedConcurrentTable<>() : new fun.bm.lophine.utils.concurrent.ConcurrentTable<>(); // Lophine - concurrent
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trackWaypoint(WaypointTransmitter waypoint) {
|
||||||
|
- // Folia - region threading
|
||||||
|
+ // Lophine start - unsafe waypoint bar
|
||||||
|
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||||
|
+ this.waypoints.add(waypoint);
|
||||||
|
+
|
||||||
|
+ for (ServerPlayer serverPlayer : this.players) {
|
||||||
|
+ this.createConnection(serverPlayer, waypoint);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - unsafe waypoint bar
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateWaypoint(WaypointTransmitter waypoint) {
|
||||||
|
if (this.waypoints.contains(waypoint)) {
|
||||||
|
- Map<ServerPlayer, WaypointTransmitter.Connection> map = Tables.transpose(this.connections).row(waypoint);
|
||||||
|
- SetView<ServerPlayer> set = Sets.difference(this.players, map.keySet());
|
||||||
|
+ java.util.List<Entry<ServerPlayer, WaypointTransmitter.Connection>> map = this.connections.getXZ(waypoint); // Lophine - concurrent
|
||||||
|
+ Set<ServerPlayer> players1 = new HashSet<>(); // Lophine - concurrent
|
||||||
|
+ if (!map.isEmpty()) map.forEach((entry) -> players1.add(entry.getKey())); // Lophine - concurrent
|
||||||
|
+ SetView<ServerPlayer> set = Sets.difference(this.players, players1); // Lophine - concurrent
|
||||||
|
|
||||||
|
- for (Entry<ServerPlayer, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
||||||
|
+ for (Entry<ServerPlayer, WaypointTransmitter.Connection> entry : map) { // Lophine - concurrent
|
||||||
|
this.updateConnection(entry.getKey(), waypoint, entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -43,26 +52,65 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void untrackWaypoint(WaypointTransmitter waypoint) {
|
||||||
|
- this.connections.column(waypoint).forEach((serverPlayer, connection) -> connection.disconnect());
|
||||||
|
- Tables.transpose(this.connections).row(waypoint).clear();
|
||||||
|
+ this.connections.getXZ(waypoint).forEach((entry) -> {
|
||||||
|
+ entry.getValue().disconnect();
|
||||||
|
+ this.connections.remove(entry.getKey(), waypoint, entry.getValue());
|
||||||
|
+ }); // Lophine - concurrent
|
||||||
|
this.waypoints.remove(waypoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(ServerPlayer player) {
|
||||||
|
// Folia - region threading
|
||||||
|
+ // Lophine start - unsafe waypoint bar
|
||||||
|
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||||
|
+ this.players.add(player);
|
||||||
|
+
|
||||||
|
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
||||||
|
+ this.createConnection(player, waypointTransmitter);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (player.isTransmittingWaypoint()) {
|
||||||
|
+ this.trackWaypoint((WaypointTransmitter)player);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - unsafe waypoint bar
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePlayer(ServerPlayer player) {
|
||||||
|
// Folia - region threading
|
||||||
|
+ // Lophine start - unsafe waypoint bar
|
||||||
|
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||||
|
+ java.util.List<Entry<WaypointTransmitter, WaypointTransmitter.Connection>> map = this.connections.getYZ(player); // Lophine - concurrent
|
||||||
|
+ Set<WaypointTransmitter> waypoints1 = new HashSet<>();// Lophine - concurrent
|
||||||
|
+ if (!map.isEmpty()) map.forEach((entry) -> waypoints1.add(entry.getKey()));// Lophine - concurrent
|
||||||
|
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, waypoints1); // Lophine - concurrent
|
||||||
|
+
|
||||||
|
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : map) { // Lophine - concurrent
|
||||||
|
+ this.updateConnection(player, entry.getKey(), entry.getValue());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (WaypointTransmitter waypointTransmitter : set) {
|
||||||
|
+ this.createConnection(player, waypointTransmitter);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - unsafe waypoint bar
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePlayer(ServerPlayer player) {
|
||||||
|
// Folia - region threading
|
||||||
|
+ // Lophine start - unsafe waypoint bar
|
||||||
|
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||||
|
+ this.connections.getYZ(player).forEach((entry) -> {
|
||||||
|
+ entry.getValue().disconnect();
|
||||||
|
+ this.connections.remove(player, entry.getKey(), entry.getValue());
|
||||||
|
+ }); // Lophine - concurrent
|
||||||
|
+ this.untrackWaypoint((WaypointTransmitter)player);
|
||||||
|
+ this.players.remove(player);
|
||||||
|
+ // Lophine end - unsafe waypoint bar
|
||||||
|
}
|
||||||
|
|
||||||
|
public void breakAllConnections() {
|
||||||
|
- this.connections.values().forEach(WaypointTransmitter.Connection::disconnect);
|
||||||
|
- this.connections.clear();
|
||||||
|
+ java.util.List<WaypointTransmitter.Connection> map = this.connections.getAllZ(); // Lophine - concurrent
|
||||||
|
+ if (!map.isEmpty()) map.forEach(WaypointTransmitter.Connection::disconnect); // Lophine - concurrent
|
||||||
|
+ this.connections.clearAll(); // Lophine - concurrent
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remakeConnections(WaypointTransmitter waypoint) {
|
||||||
|
@@ -83,13 +131,19 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||||
|
if (player != waypoint) {
|
||||||
|
if (isLocatorBarEnabledFor(player)) {
|
||||||
|
waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection -> {
|
||||||
|
- this.connections.put(player, waypoint, connection);
|
||||||
|
+ this.connections.putOrUpdate(player, waypoint, connection);
|
||||||
|
connection.connect();
|
||||||
|
}, () -> {
|
||||||
|
- WaypointTransmitter.Connection connection = this.connections.remove(player, waypoint);
|
||||||
|
- if (connection != null) {
|
||||||
|
- connection.disconnect();
|
||||||
|
- }
|
||||||
|
+ // Lophine start - concurrent
|
||||||
|
+ java.util.List<WaypointTransmitter.Connection> c = this.connections.getZ(player, waypoint);
|
||||||
|
+ if (c.isEmpty()) return; // Lophine - concurrent
|
||||||
|
+ c.forEach((connection) -> {
|
||||||
|
+ this.connections.remove(player, waypoint, connection);
|
||||||
|
+ if (connection != null) {
|
||||||
|
+ connection.disconnect();
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ // Lophine end - concurrent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -103,10 +157,12 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||||
|
} else {
|
||||||
|
waypoint.makeWaypointConnectionWith(player).ifPresentOrElse(connection1 -> {
|
||||||
|
connection1.connect();
|
||||||
|
- this.connections.put(player, waypoint, connection1);
|
||||||
|
+ this.connections.putOrUpdate(player, waypoint, connection1);
|
||||||
|
}, () -> {
|
||||||
|
connection.disconnect();
|
||||||
|
- this.connections.remove(player, waypoint);
|
||||||
|
+ java.util.List<WaypointTransmitter.Connection> c = this.connections.getZ(player, waypoint); // Lophine - concurrent
|
||||||
|
+ if (c.isEmpty()) return; // Lophine - concurrent
|
||||||
|
+ c.forEach((connection1) -> this.connections.remove(player, waypoint, connection1)); // Lophine - concurrent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
-92
@@ -1,92 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
|
||||||
Date: Mon, 7 Jul 2025 18:19:00 +0800
|
|
||||||
Subject: [PATCH] Add config to enable waypoint command & bar
|
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
|
||||||
index dc5a558c72a5a7ab8a650262c6a1a2dc5142b8fc..9eee09ecc18abcc5972f65938ba8607dfeede026 100644
|
|
||||||
--- a/net/minecraft/commands/Commands.java
|
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
|
||||||
@@ -259,7 +259,11 @@ public class Commands {
|
|
||||||
TimeCommand.register(this.dispatcher);
|
|
||||||
TitleCommand.register(this.dispatcher, context);
|
|
||||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
|
||||||
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
|
||||||
+ // Lophine start - unsafe waypoint bar
|
|
||||||
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) {
|
|
||||||
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - unsafe waypoint bar
|
|
||||||
WeatherCommand.register(this.dispatcher);
|
|
||||||
WorldBorderCommand.register(this.dispatcher);
|
|
||||||
if (JvmProfiler.INSTANCE.isAvailable()) {
|
|
||||||
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
||||||
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..52fd730998535ea071bfc99b7cc2c254b9b656d7 100644
|
|
||||||
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
||||||
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
|
||||||
@@ -22,7 +22,14 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void trackWaypoint(WaypointTransmitter waypoint) {
|
|
||||||
- // Folia - region threading
|
|
||||||
+ // Lophine start - unsafe waypoint bar
|
|
||||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
|
||||||
+ this.waypoints.add(waypoint);
|
|
||||||
+
|
|
||||||
+ for (ServerPlayer serverPlayer : this.players) {
|
|
||||||
+ this.createConnection(serverPlayer, waypoint);
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - unsafe waypoint bar
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@@ -50,14 +57,48 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
|
||||||
|
|
||||||
public void addPlayer(ServerPlayer player) {
|
|
||||||
// Folia - region threading
|
|
||||||
+ // Lophine start - unsafe waypoint bar
|
|
||||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
|
||||||
+ this.players.add(player);
|
|
||||||
+
|
|
||||||
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
|
||||||
+ this.createConnection(player, waypointTransmitter);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (player.isTransmittingWaypoint()) {
|
|
||||||
+ this.trackWaypoint((WaypointTransmitter)player);
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - unsafe waypoint bar
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePlayer(ServerPlayer player) {
|
|
||||||
// Folia - region threading
|
|
||||||
+ // Lophine start - unsafe waypoint bar
|
|
||||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
|
||||||
+ Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.row(player);
|
|
||||||
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
|
|
||||||
+
|
|
||||||
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
|
|
||||||
+ this.updateConnection(player, entry.getKey(), entry.getValue());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (WaypointTransmitter waypointTransmitter : set) {
|
|
||||||
+ this.createConnection(player, waypointTransmitter);
|
|
||||||
+ }
|
|
||||||
+ // Lophine end - unsafe waypoint bar
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePlayer(ServerPlayer player) {
|
|
||||||
// Folia - region threading
|
|
||||||
+ // Lophine start - unsafe waypoint bar
|
|
||||||
+ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
|
||||||
+ this.connections.row(player).values().removeIf(connection -> {
|
|
||||||
+ connection.disconnect();
|
|
||||||
+ return true;
|
|
||||||
+ });
|
|
||||||
+ this.untrackWaypoint((WaypointTransmitter)player);
|
|
||||||
+ this.players.remove(player);
|
|
||||||
+ // Lophine end - unsafe waypoint bar
|
|
||||||
}
|
|
||||||
|
|
||||||
public void breakAllConnections() {
|
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 2 Jul 2025 23:36:25 +0800
|
||||||
|
Subject: [PATCH] Fix datapack command save function
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
|
index df5ff1cc7b289c3f52723d4e7b418e79ae6c3082..8f74af03cf0af0960b1016c8304ca0e440969215 100644
|
||||||
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -2358,6 +2358,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||||
|
+ public void saveDatapacks(Collection<String> selectedIds) {
|
||||||
|
+ this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
|
||||||
|
+ WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
|
||||||
|
+ getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
|
||||||
|
+ );
|
||||||
|
+ this.worldData.setDataConfiguration(worldDataConfiguration);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||||
|
+
|
||||||
|
public CompletableFuture<Void> reloadResources(Collection<String> selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) {
|
||||||
|
// Paper end - Add ServerResourcesReloadedEvent
|
||||||
|
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
|
||||||
|
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
|
||||||
|
index a5032b34752061d61fd9ddb4db828d35e403f5e7..3eaa9c85d06f6ecc8ed639d8befa861439390eb7 100644
|
||||||
|
--- a/net/minecraft/server/commands/DataPackCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/DataPackCommand.java
|
||||||
|
@@ -98,7 +98,7 @@ public class DataPackCommand {
|
||||||
|
dispatcher.register(
|
||||||
|
Commands.literal("datapack")
|
||||||
|
.requires(Commands.hasPermission(2))
|
||||||
|
- /*.then( // Luminol - Add back read-only datapack command
|
||||||
|
+ .then(
|
||||||
|
Commands.literal("enable")
|
||||||
|
.then(
|
||||||
|
Commands.argument("name", StringArgumentType.string())
|
||||||
|
@@ -160,11 +160,11 @@ public class DataPackCommand {
|
||||||
|
.suggests(SELECTED_PACKS)
|
||||||
|
.executes(commandContext -> disablePack(commandContext.getSource(), getPack(commandContext, "name", false)))
|
||||||
|
)
|
||||||
|
- )*/ // Luminol - Add back read-only datapack command
|
||||||
|
+ )
|
||||||
|
.then(
|
||||||
|
Commands.literal("list")
|
||||||
|
.executes(commandContext -> listPacks(commandContext.getSource()))
|
||||||
|
- // .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource()))) // Luminol - Add back read-only datapack command
|
||||||
|
+ .then(Commands.literal("available").executes(commandContext -> listAvailablePacks(commandContext.getSource())))
|
||||||
|
.then(Commands.literal("enabled").executes(commandContext -> listEnabledPacks(commandContext.getSource())))
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
@@ -252,7 +252,7 @@ public class DataPackCommand {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int listPacks(CommandSourceStack source) {
|
||||||
|
- return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
|
||||||
|
+ return listEnabledPacks(source) + listAvailablePacks(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int listAvailablePacks(CommandSourceStack source) {
|
||||||
|
@@ -280,7 +280,7 @@ public class DataPackCommand {
|
||||||
|
|
||||||
|
private static int listEnabledPacks(CommandSourceStack source) {
|
||||||
|
PackRepository packRepository = source.getServer().getPackRepository();
|
||||||
|
- // packRepository.reload(); // Luminol - Add back read-only datapack command
|
||||||
|
+ packRepository.reload();
|
||||||
|
Collection<? extends Pack> selectedPacks = packRepository.getSelectedPacks();
|
||||||
|
if (selectedPacks.isEmpty()) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.datapack.list.enabled.none"), false);
|
||||||
|
diff --git a/net/minecraft/server/commands/ReloadCommand.java b/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
index b540a3c3a02f7242578a63477e34b9063e86f1d2..bc999de32931558d0d8dc26264653dd63c1cad19 100644
|
||||||
|
--- a/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/ReloadCommand.java
|
||||||
|
@@ -16,11 +16,17 @@ public class ReloadCommand {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
|
public static void reloadPacks(Collection<String> selectedIds, CommandSourceStack source) {
|
||||||
|
+ // Lophine start - region thread skip reload // TODO - add reload support
|
||||||
|
+ source.getServer().saveDatapacks(selectedIds);
|
||||||
|
+ source.getSender().sendMessage("You need to restart server to load datapacks update.");
|
||||||
|
+ if (false) {
|
||||||
|
source.getServer().reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally(throwable -> { // Paper - Add ServerResourcesReloadedEvent
|
||||||
|
LOGGER.warn("Failed to execute reload", throwable);
|
||||||
|
source.sendFailure(Component.translatable("commands.reload.failure"));
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - region thread skip reload // TODO - add reload support
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
|
||||||
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
|
|||||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
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
|
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
index 8405157ec35a443e238fa6866772c839621d73d7..67f3454e6479abb241a7d94699d4f7bec22da56b 100644
|
index 1cefe9d83788dafc293aeb6d1b5e635211094b2a..e423d5c0614823ce9a8fbd32b672232e5758e3c1 100644
|
||||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||||
@@ -334,6 +334,8 @@ public final class RegionizedServer {
|
@@ -336,6 +336,8 @@ public final class RegionizedServer {
|
||||||
}
|
}
|
||||||
// Luminol end - Add a config to enable tick command
|
// Luminol end - Add a config to enable tick command
|
||||||
|
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 29 Oct 2025 00:09:09 +0800
|
||||||
|
Subject: [PATCH] Leaves: Configurable trading with the void
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
index 7584ba257d61bf650d83a2316ff012df928d54f3..4d71cc3b643f6f594c90f2f8f9e5b820ebdff080 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
@@ -2901,7 +2901,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
// Spigot start
|
||||||
|
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
|
||||||
|
// Paper start - Fix merchant inventory not closing on entity removal
|
||||||
|
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
|
||||||
|
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Leaves - Configurable trading with the void
|
||||||
|
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
|
||||||
|
}
|
||||||
|
// Paper end - Fix merchant inventory not closing on entity removal
|
||||||
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
|
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..6c1f4f943a5be5f2e43a82cca52ca76a98226915 100644
|
||||||
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
|
@@ -649,7 +649,7 @@ public abstract class PlayerList {
|
||||||
|
player.stopRiding();
|
||||||
|
rootVehicle.getPassengersAndSelf().forEach(entity -> {
|
||||||
|
// Paper start - Fix villager boat exploit
|
||||||
|
- if (entity instanceof net.minecraft.world.entity.npc.AbstractVillager villager) {
|
||||||
|
+ if (!fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade && entity instanceof net.minecraft.world.entity.npc.AbstractVillager villager) { // Leaves - Configurable trading with the void
|
||||||
|
final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer();
|
||||||
|
if (human != null) {
|
||||||
|
villager.setTradingPlayer(null);
|
||||||
|
diff --git a/net/minecraft/world/inventory/MerchantMenu.java b/net/minecraft/world/inventory/MerchantMenu.java
|
||||||
|
index d59f67ffe34201c63e3d9706a4434f33b6732edb..c635c7211bff9d190b7035b284dda162334fd5c2 100644
|
||||||
|
--- a/net/minecraft/world/inventory/MerchantMenu.java
|
||||||
|
+++ b/net/minecraft/world/inventory/MerchantMenu.java
|
||||||
|
@@ -74,6 +74,7 @@ public class MerchantMenu extends AbstractContainerMenu {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stillValid(Player player) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.OldFeatureConfig.villagerVoidTrade) return this.trader.getTradingPlayer() == player; // Leaves - Configurable trading with the void
|
||||||
|
if (!checkReachable) return true; // Paper - checkReachable
|
||||||
|
return this.trader.stillValid(player);
|
||||||
|
}
|
||||||
+4
-4
@@ -446,10 +446,10 @@ index 10b2cc20bbf3b70e4e09dbbe14b90506e6366158..1535bb8cec8692e8d26eaff090288f1b
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b64e4409b0 100644
|
index 3fd172f82216fa35c36e5f563819a6f01ffd4ea4..419bc939e19a306b33d4d387007c6acbae73fba3 100644
|
||||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
@@ -148,7 +148,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -144,7 +144,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
public void setItem(int index, ItemStack stack) {
|
public void setItem(int index, ItemStack stack) {
|
||||||
this.unpackLootTable(null);
|
this.unpackLootTable(null);
|
||||||
this.getItems().set(index, stack);
|
this.getItems().set(index, stack);
|
||||||
@@ -458,7 +458,7 @@ index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b6
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -770,9 +770,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -740,9 +740,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
if (item.isEmpty()) {
|
if (item.isEmpty()) {
|
||||||
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
// Spigot start - SPIGOT-6693, SimpleContainer#setItem
|
||||||
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size
|
||||||
@@ -469,4 +469,4 @@ index aca3303a043144894ae20ddc43abc55790db44ad..55cbf9b4cc568fb9b418433f597ed6b6
|
|||||||
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
|
+ stack = stack.split(Math.min(destination.getMaxStackSize(), stack.getMaxStackSize())); // Leaves - item over-stack util
|
||||||
}
|
}
|
||||||
// Spigot end
|
// Spigot end
|
||||||
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - Use vanilla hopper logic
|
//IGNORE_TILE_UPDATES.set(Boolean.TRUE); // Paper - Perf: Optimize Hoppers // Folia - region threading // Luminol - vanilla hopper
|
||||||
+1
-1
@@ -23,7 +23,7 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
|
|||||||
+ // Leaves end - servux
|
+ // Leaves end - servux
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index eb3aef1f5198592eda5dafe84b91271e861b4135..576dde41a4b48aac9079cca902f4371a31470af3 100644
|
index 4d71cc3b643f6f594c90f2f8f9e5b820ebdff080..7fb095c544294796768ce19c4409416e2848e296 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Sun, 16 Nov 2025 17:47:48 +0800
|
||||||
|
Subject: [PATCH] LeavesHooks
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
|
index d9fd093f59987f471627ff20cfd2eb1a3c0dea64..78c6d425589b8147c33583ac46d6f21ec5dbefaa 100644
|
||||||
|
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
|
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
|
@@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
-public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||||
|
+public class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
|
||||||
|
|
||||||
+1
-1
@@ -8,7 +8,7 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18
|
|||||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
index 593dbcda4b497291eb1ecdc64b947a8d279f8be6..cb863a36fc67e993956ec3be655e6e4b9764c051 100644
|
index 6c1f4f943a5be5f2e43a82cca52ca76a98226915..8e2775e873c92beed6a0e4e8ce1304ab8ca6e8d1 100644
|
||||||
--- a/net/minecraft/server/players/PlayerList.java
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
+++ b/net/minecraft/server/players/PlayerList.java
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
@@ -1087,6 +1087,10 @@ public abstract class PlayerList {
|
@@ -1087,6 +1087,10 @@ public abstract class PlayerList {
|
||||||
+1
-1
@@ -39,7 +39,7 @@ index cf72cb8b418239b56c755486b03a321672e16bc3..b69c06607ca900beeebf4892a978442d
|
|||||||
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
|
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
|
||||||
if (awtException != null) {
|
if (awtException != null) {
|
||||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
index c93feb64b6088a4878fcdb6e7c733a5f37e9385b..79c911003c7b1c3d94e7e9d3974eeadcc16bde3a 100644
|
index 392d75548f7eb271a6320ac30eb301a61071d465..0e278f7b9ed85ce8c3cedd9154f817b30ff1e48a 100644
|
||||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||||
+16
-25
@@ -20,7 +20,7 @@ index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c9
|
|||||||
Set<CriterionTrigger.Listener<T>> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
|
Set<CriterionTrigger.Listener<T>> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak
|
||||||
if (set != null && !set.isEmpty()) {
|
if (set != null && !set.isEmpty()) {
|
||||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||||
index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4beca0969 100644
|
index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..58694e28b3ff85ef038fe2ada2672e6d3b074fa4 100644
|
||||||
--- a/net/minecraft/network/Connection.java
|
--- a/net/minecraft/network/Connection.java
|
||||||
+++ b/net/minecraft/network/Connection.java
|
+++ b/net/minecraft/network/Connection.java
|
||||||
@@ -96,7 +96,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
@@ -96,7 +96,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||||
@@ -28,12 +28,12 @@ index 66ec0424a46dcd49cf44467357d80b1a2d84d3b2..04ae8de63af0a8abe578f14c8ef85fd4
|
|||||||
private volatile PacketListener disconnectListener;
|
private volatile PacketListener disconnectListener;
|
||||||
@Nullable
|
@Nullable
|
||||||
- private volatile PacketListener packetListener;
|
- private volatile PacketListener packetListener;
|
||||||
+ protected volatile PacketListener packetListener; // Leaves - private -> protected
|
+ public volatile PacketListener packetListener; // Leaves - private -> protected // Lophine protected -> public
|
||||||
@Nullable
|
@Nullable
|
||||||
private DisconnectionDetails disconnectionDetails;
|
private DisconnectionDetails disconnectionDetails;
|
||||||
private boolean encrypted;
|
private boolean encrypted;
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786e46148b1 100644
|
index 8f74af03cf0af0960b1016c8304ca0e440969215..c33757d3e53a97148c11f601cde0b6127d663f11 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -347,6 +347,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -347,6 +347,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
@@ -57,7 +57,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
|||||||
// Folia start - region threading
|
// Folia start - region threading
|
||||||
// halt scheduler
|
// halt scheduler
|
||||||
// don't wait, we may be on a scheduler thread
|
// don't wait, we may be on a scheduler thread
|
||||||
@@ -1588,7 +1595,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1593,7 +1600,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
int i = this.pauseWhileEmptySeconds() * 20;
|
int i = this.pauseWhileEmptySeconds() * 20;
|
||||||
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
|
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
|
||||||
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
|
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
|
||||||
@@ -66,7 +66,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
|||||||
this.emptyTicks++;
|
this.emptyTicks++;
|
||||||
} else {
|
} else {
|
||||||
this.emptyTicks = 0;
|
this.emptyTicks = 0;
|
||||||
@@ -1912,6 +1919,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1917,6 +1924,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
|
||||||
public void tickConnection() {
|
public void tickConnection() {
|
||||||
this.getConnection().tick();
|
this.getConnection().tick();
|
||||||
@@ -74,7 +74,7 @@ index b156b5c635f931a3d4abc0584591f90476d011a6..81726e5782d25ff35a2bea8820a62786
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void synchronizeTime(ServerLevel level) {
|
private void synchronizeTime(ServerLevel level) {
|
||||||
@@ -2983,6 +2991,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -2988,6 +2996,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ index f2286b96b8f40b4588f817913c42ae7b4a92340f..e6c7bbb023000b9de90c1256274ff5ab
|
|||||||
playerList.op(gameProfile);
|
playerList.op(gameProfile);
|
||||||
i++;
|
i++;
|
||||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f604b0d6890 100644
|
index 0e278f7b9ed85ce8c3cedd9154f817b30ff1e48a..09d4b1d68c3f046ef304016a1afe7a3038dfae3e 100644
|
||||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
@@ -162,6 +162,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
@@ -162,6 +162,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||||
@@ -239,18 +239,9 @@ index 79c911003c7b1c3d94e7e9d3974eeadcc16bde3a..328428f0ef8a2305f661c167e6fe1f60
|
|||||||
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
|
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
|
||||||
if (this.convertOldUsers()) {
|
if (this.convertOldUsers()) {
|
||||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||||
index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348fcbaf9ded 100644
|
index 70740381c6501c1a518c52b24381edd16792507f..8ad6d5a2522cfbe316fec2c3b918e2e1b9af3d1b 100644
|
||||||
--- a/net/minecraft/server/level/ChunkMap.java
|
--- a/net/minecraft/server/level/ChunkMap.java
|
||||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||||
@@ -134,7 +134,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
||||||
public final AtomicInteger tickingGenerated = new AtomicInteger(); // Paper - public
|
|
||||||
private final String storageName;
|
|
||||||
//private final PlayerMap playerMap = new PlayerMap(); // Folia - region threading
|
|
||||||
- //public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
|
|
||||||
+ public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap = new Int2ObjectOpenHashMap<>(); // Folia - region threading
|
|
||||||
private final Long2ByteMap chunkTypeCache = new Long2ByteOpenHashMap();
|
|
||||||
// Paper - rewrite chunk system
|
|
||||||
public int serverViewDistance;
|
|
||||||
@@ -1309,6 +1309,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
@@ -1309,6 +1309,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||||
}
|
}
|
||||||
} else if (this.seenBy.remove(player.connection)) {
|
} else if (this.seenBy.remove(player.connection)) {
|
||||||
@@ -266,7 +257,7 @@ index 70740381c6501c1a518c52b24381edd16792507f..5e31b499a894113b4be1982a1071348f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6cf992049 100644
|
index 7fb095c544294796768ce19c4409416e2848e296..3393fb585747aaf3fa270c4bfe06ed4e9174d519 100644
|
||||||
--- a/net/minecraft/server/level/ServerLevel.java
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
@@ -207,6 +207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -207,6 +207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
@@ -298,7 +289,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
|
|||||||
@Override
|
@Override
|
||||||
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
|
public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||||
Optional<Holder<PoiType>> optional = PoiTypes.forState(oldState);
|
Optional<Holder<PoiType>> optional = PoiTypes.forState(oldState);
|
||||||
@@ -2826,6 +2834,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2827,6 +2835,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
// ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
|
||||||
if (entity instanceof ServerPlayer serverPlayer) {
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
ServerLevel.this.players.add(serverPlayer);
|
ServerLevel.this.players.add(serverPlayer);
|
||||||
@@ -310,7 +301,7 @@ index 576dde41a4b48aac9079cca902f4371a31470af3..952b92c55d7192791a19ecebe80894f6
|
|||||||
if (serverPlayer.isReceivingWaypoints()) {
|
if (serverPlayer.isReceivingWaypoints()) {
|
||||||
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
|
ServerLevel.this.getWaypointManager().addPlayer(serverPlayer);
|
||||||
}
|
}
|
||||||
@@ -2913,6 +2926,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
@@ -2914,6 +2927,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
ServerLevel.this.getChunkSource().removeEntity(entity);
|
ServerLevel.this.getChunkSource().removeEntity(entity);
|
||||||
if (entity instanceof ServerPlayer serverPlayer) {
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
ServerLevel.this.players.remove(serverPlayer);
|
ServerLevel.this.players.remove(serverPlayer);
|
||||||
@@ -434,7 +425,7 @@ index 144a2644c15f276f02bb3be859dc5d05a677ac55..c6a89e8936cffa49b3de153ed3c40e3c
|
|||||||
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency
|
||||||
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
|
GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string);
|
||||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74af2697442 100644
|
index 8e2775e873c92beed6a0e4e8ce1304ab8ca6e8d1..580f114fd99b017403c61e994d0c947d00e5115d 100644
|
||||||
--- a/net/minecraft/server/players/PlayerList.java
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
+++ b/net/minecraft/server/players/PlayerList.java
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
@@ -425,6 +425,19 @@ public abstract class PlayerList {
|
@@ -425,6 +425,19 @@ public abstract class PlayerList {
|
||||||
@@ -445,7 +436,7 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
|
|||||||
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
|
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
|
||||||
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
|
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
|
||||||
+ if (bot != null) {
|
+ if (bot != null) {
|
||||||
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false);
|
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, true);
|
||||||
+ }
|
+ }
|
||||||
+ this.server.getBotList().bots.forEach(bot1 -> {
|
+ this.server.getBotList().bots.forEach(bot1 -> {
|
||||||
+ bot1.sendPlayerInfo(player);
|
+ bot1.sendPlayerInfo(player);
|
||||||
@@ -520,7 +511,7 @@ index cb863a36fc67e993956ec3be655e6e4b9764c051..908ec29a6e285122d1a8a43dc547b74a
|
|||||||
|
|
||||||
public boolean canBypassPlayerLimit(GameProfile profile) {
|
public boolean canBypassPlayerLimit(GameProfile profile) {
|
||||||
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd13444f4ad 100644
|
index 65a4956ba2f0e38da7ae4f8cd7ed6e4b02c015a9..044ded5ec81905e38efe8812ff6d50259d761385 100644
|
||||||
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
|
||||||
@@ -24,6 +24,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
@@ -24,6 +24,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||||
@@ -535,7 +526,7 @@ index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd1
|
|||||||
this.waypoints.add(waypoint);
|
this.waypoints.add(waypoint);
|
||||||
|
|
||||||
for (ServerPlayer serverPlayer : this.players) {
|
for (ServerPlayer serverPlayer : this.players) {
|
||||||
@@ -59,6 +64,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
@@ -63,6 +68,11 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
|
||||||
// Folia - region threading
|
// Folia - region threading
|
||||||
// Lophine start - unsafe waypoint bar
|
// Lophine start - unsafe waypoint bar
|
||||||
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
if (!fun.bm.lophine.config.modules.experiment.CommandConfig.waypoint) return;
|
||||||
@@ -548,7 +539,7 @@ index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd1
|
|||||||
|
|
||||||
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index 47ef63061737f3efdb0ce7ec71a8d9c920385bb0..674c4cc7443545f7e333d2bcec9e5fc98000ecae 100644
|
index a8b6e89035579557b59a20ddbe9b32943e6b7164..477241699752567df7695d33fa629fb1d5109e0a 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
+1
-1
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
|||||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
index 29788fedd54b8411c9c8872b4d83b037874fb5f0..24af6821694768058dc0146220877ab70066b5f9 100644
|
index 0d906776e10605ecfe7c681dbf313cf25080d2e8..1f44a59e46f86ca055e89631d831a38f4c3e238e 100644
|
||||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
@@ -754,6 +754,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
@@ -754,6 +754,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||||
+1
-1
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
|||||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
index 908ec29a6e285122d1a8a43dc547b74af2697442..1bf1731e43278b71423fee5d92401c48d6dabaca 100644
|
index 580f114fd99b017403c61e994d0c947d00e5115d..11c1eb6995ec3aa896815efa59477096c39089d1 100644
|
||||||
--- a/net/minecraft/server/players/PlayerList.java
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
+++ b/net/minecraft/server/players/PlayerList.java
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
@@ -1247,6 +1247,7 @@ public abstract class PlayerList {
|
@@ -1247,6 +1247,7 @@ public abstract class PlayerList {
|
||||||
+6
-6
@@ -10,10 +10,10 @@ Licensed under: MIT
|
|||||||
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
|
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
index 55cbf9b4cc568fb9b418433f597ed6b64e4409b0..8449623a313edbe95941a2e328fe47269015f7fb 100644
|
index 419bc939e19a306b33d4d387007c6acbae73fba3..96445438c5b4202e3fc93bece778ad0d7312d41c 100644
|
||||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
@@ -232,8 +232,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -228,8 +228,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ index 55cbf9b4cc568fb9b418433f597ed6b64e4409b0..8449623a313edbe95941a2e328fe4726
|
|||||||
setChanged(level, pos, state);
|
setChanged(level, pos, state);
|
||||||
// Leaves start - Lithium Sleeping Block Entity
|
// Leaves start - Lithium Sleeping Block Entity
|
||||||
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
|
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
|
||||||
@@ -464,6 +486,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -461,6 +483,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
// Paper end - Perf: Optimize Hoppers
|
// Paper end - Perf: Optimize Hoppers
|
||||||
|
|
||||||
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
|
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
|
||||||
@@ -55,10 +55,10 @@ index 55cbf9b4cc568fb9b418433f597ed6b64e4409b0..8449623a313edbe95941a2e328fe4726
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ // Leaves end - hopper counter
|
+ // Leaves end - hopper counter
|
||||||
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level, pos, blockEntity) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
|
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
|
||||||
if (attachedContainer == null) {
|
if (attachedContainer == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -554,6 +583,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -536,6 +565,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ index 55cbf9b4cc568fb9b418433f597ed6b64e4409b0..8449623a313edbe95941a2e328fe4726
|
|||||||
private static int[] getSlots(Container container, Direction direction) {
|
private static int[] getSlots(Container container, Direction direction) {
|
||||||
if (container instanceof WorldlyContainer worldlyContainer) {
|
if (container instanceof WorldlyContainer worldlyContainer) {
|
||||||
return worldlyContainer.getSlotsForFace(direction);
|
return worldlyContainer.getSlotsForFace(direction);
|
||||||
@@ -710,6 +759,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
@@ -680,6 +729,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean addItem(Container container, ItemEntity item) {
|
public static boolean addItem(Container container, ItemEntity item) {
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
Date: Mon, 3 Feb 2025 13:51:26 +0800
|
||||||
|
Subject: [PATCH] Leaves: Alternative block placement Protocol
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: MIT
|
||||||
|
|
||||||
|
This patch is Powered by
|
||||||
|
carpet-extra(https://github.com/gnembon/carpet-extra)
|
||||||
|
MasaGadget(https://github.com/plusls/MasaGadget)
|
||||||
|
litematica(https://github.com/maruohon/litematica)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
|
index 9be4bc9e78c22c12ba594b16dac6901023f0fd47..3d9c26bc8cc14e98310f557f351871b082e5023e 100644
|
||||||
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
|
@@ -2087,7 +2087,7 @@ public class ServerGamePacketListenerImpl
|
||||||
|
if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.level(), blockPos.getX() >> 4, blockPos.getZ() >> 4, 8) && this.player.canInteractWithBlock(blockPos, 1.0)) { // Folia - do not allow players to interact with blocks outside the current region
|
||||||
|
Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos));
|
||||||
|
double d = 1.0000001;
|
||||||
|
- if (Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.needIgnoreDistance() ||Math.abs(vec3.x()) < 1.0000001 && Math.abs(vec3.y()) < 1.0000001 && Math.abs(vec3.z()) < 1.0000001) { // Leaves - disableDistanceCheckForUseItem
|
||||||
|
Direction direction = hitResult.getDirection();
|
||||||
|
this.player.resetLastActionTime();
|
||||||
|
int maxY = this.player.level().getMaxY();
|
||||||
|
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||||
|
index 6db566adf2d0df1d26221eda04aa01738df6d3d2..8f112f382190d606a87f38da8bcdf8dd5f31d1c5 100644
|
||||||
|
--- a/net/minecraft/world/item/BlockItem.java
|
||||||
|
+++ b/net/minecraft/world/item/BlockItem.java
|
||||||
|
@@ -149,7 +149,7 @@ public class BlockItem extends Item {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected BlockState getPlacementState(BlockPlaceContext context) {
|
||||||
|
- BlockState stateForPlacement = this.getBlock().getStateForPlacement(context);
|
||||||
|
+ BlockState stateForPlacement = this.getBlock().getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||||
|
return stateForPlacement != null && this.canPlace(context, stateForPlacement) ? stateForPlacement : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||||
|
index 12c6c8aeec89a0a55633c62fe98f5a3aa75fd476..1f0e7c391d02b18e2c89700025713ec3d759f2ea 100644
|
||||||
|
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||||
|
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
|
||||||
|
@@ -27,14 +27,14 @@ public class StandingAndWallBlockItem extends BlockItem {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected BlockState getPlacementState(BlockPlaceContext context) {
|
||||||
|
- BlockState stateForPlacement = this.wallBlock.getStateForPlacement(context);
|
||||||
|
+ BlockState stateForPlacement = this.wallBlock.getRealStateForPlacement(context); // Leaves - alternativeBlockPlacement
|
||||||
|
BlockState blockState = null;
|
||||||
|
LevelReader level = context.getLevel();
|
||||||
|
BlockPos clickedPos = context.getClickedPos();
|
||||||
|
|
||||||
|
for (Direction direction : context.getNearestLookingDirections()) {
|
||||||
|
if (direction != this.attachmentDirection.getOpposite()) {
|
||||||
|
- BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : stateForPlacement;
|
||||||
|
+ BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getRealStateForPlacement(context) : stateForPlacement; // Leaves - alternativeBlockPlacement
|
||||||
|
if (blockState1 != null && this.canPlace(level, blockState1, clickedPos)) {
|
||||||
|
blockState = blockState1;
|
||||||
|
break;
|
||||||
|
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
|
||||||
|
index 644b9fab1d6729bf3964ebee0d6e9c46f89b8c46..634bdb554dfe757c3c9f13a79c3f644d8be4e3ea 100644
|
||||||
|
--- a/net/minecraft/world/level/block/Block.java
|
||||||
|
+++ b/net/minecraft/world/level/block/Block.java
|
||||||
|
@@ -439,6 +439,33 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||||
|
public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - alternativeBlockPlacement
|
||||||
|
+ @Nullable
|
||||||
|
+ public BlockState getRealStateForPlacement(BlockPlaceContext ctx) {
|
||||||
|
+ BlockState vanillaState = this.getStateForPlacement(ctx);
|
||||||
|
+ switch (fun.bm.lophine.config.modules.function.protocol.AlternativeBlockPlacementProtocolConfig.alternativeBlockPlacement) {
|
||||||
|
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET -> {
|
||||||
|
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacement(this, ctx);
|
||||||
|
+ if (tryState != null) {
|
||||||
|
+ return tryState;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.CARPET_FIX -> {
|
||||||
|
+ BlockState tryState = org.leavesmc.leaves.protocol.CarpetAlternativeBlockPlacement.alternativeBlockPlacementFix(this, ctx);
|
||||||
|
+ if (tryState != null) {
|
||||||
|
+ return tryState;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ case fun.bm.lophine.enums.EnumAlternativePlaceType.LITEMATICA -> {
|
||||||
|
+ if (vanillaState != null) {
|
||||||
|
+ return org.leavesmc.leaves.protocol.LitematicaEasyPlaceProtocol.applyPlacementProtocol(vanillaState, ctx);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return vanillaState;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - alternativeBlockPlacement
|
||||||
|
+
|
||||||
|
@Nullable
|
||||||
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
|
return this.defaultBlockState();
|
||||||
@@ -0,0 +1,564 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Sun, 16 Nov 2025 15:48:12 +0800
|
||||||
|
Subject: [PATCH] Leaves: Replay Mod API
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves) & ReplayMod (https://github.com/ReplayMod)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
This patch is Powered by ReplayMod (https://github.com/ReplayMod)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java
|
||||||
|
index 8c005a7b9480da7c124c5bd5bfccd5ca83abbcb1..a814a67f321662f05e2c5f81666f75e128bf4ea7 100644
|
||||||
|
--- a/net/minecraft/commands/CommandSourceStack.java
|
||||||
|
+++ b/net/minecraft/commands/CommandSourceStack.java
|
||||||
|
@@ -580,7 +580,7 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getOnlinePlayerNames() {
|
||||||
|
- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players
|
||||||
|
+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||||
|
index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378fa55b6c3 100644
|
||||||
|
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||||
|
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
|
||||||
|
@@ -128,11 +128,12 @@ public class EntitySelector {
|
||||||
|
return this.findPlayers(source);
|
||||||
|
} else if (this.playerName != null) {
|
||||||
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
|
||||||
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
||||||
|
return playerByName == null ? List.of() : List.of(playerByName);
|
||||||
|
} else if (this.entityUUID != null) {
|
||||||
|
for (ServerLevel serverLevel : source.getServer().getAllLevels()) {
|
||||||
|
Entity entity = serverLevel.getEntity(this.entityUUID);
|
||||||
|
- if (entity != null) {
|
||||||
|
+ if (entity != null && !(entity instanceof org.leavesmc.leaves.replay.ServerPhotographer)) {
|
||||||
|
if (entity.getType().isEnabled(source.enabledFeatures())) {
|
||||||
|
return List.of(entity);
|
||||||
|
}
|
||||||
|
@@ -146,7 +147,7 @@ public class EntitySelector {
|
||||||
|
AABB absoluteAabb = this.getAbsoluteAabb(vec3);
|
||||||
|
if (this.currentEntity) {
|
||||||
|
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, null);
|
||||||
|
- return source.getEntity() != null && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of();
|
||||||
|
+ return source.getEntity() != null && !(source.getEntity() instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(source.getEntity()) ? List.of(source.getEntity()) : List.of(); // Leaves - skip photographer
|
||||||
|
} else {
|
||||||
|
Predicate<Entity> predicate = this.getPredicate(vec3, absoluteAabb, source.enabledFeatures());
|
||||||
|
List<Entity> list = new ObjectArrayList<>();
|
||||||
|
@@ -157,6 +158,7 @@ public class EntitySelector {
|
||||||
|
this.addEntities(list, serverLevel1, absoluteAabb, predicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ list.removeIf(entity -> entity instanceof org.leavesmc.leaves.replay.ServerPhotographer); // Leaves - skip photographer
|
||||||
|
|
||||||
|
return this.sortAndLimit(vec3, list);
|
||||||
|
}
|
||||||
|
@@ -192,9 +194,11 @@ public class EntitySelector {
|
||||||
|
this.checkPermissions(source);
|
||||||
|
if (this.playerName != null) {
|
||||||
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName);
|
||||||
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
||||||
|
return playerByName == null ? List.of() : List.of(playerByName);
|
||||||
|
} else if (this.entityUUID != null) {
|
||||||
|
ServerPlayer playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID);
|
||||||
|
+ playerByName = playerByName instanceof org.leavesmc.leaves.replay.ServerPhotographer ? null : playerByName; // Leaves - skip photographer
|
||||||
|
return playerByName == null ? List.of() : List.of(playerByName);
|
||||||
|
} else {
|
||||||
|
Vec3 vec3 = this.position.apply(source.getPosition());
|
||||||
|
@@ -206,11 +210,11 @@ public class EntitySelector {
|
||||||
|
int resultLimit = this.getResultLimit();
|
||||||
|
List<ServerPlayer> players;
|
||||||
|
if (this.isWorldLimited()) {
|
||||||
|
- players = source.getLevel().getPlayers(predicate, resultLimit);
|
||||||
|
+ players = source.getLevel().getPlayers((player -> !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer) && predicate.test(player)), resultLimit); // Leaves - skip photographer
|
||||||
|
} else {
|
||||||
|
players = new ObjectArrayList<>();
|
||||||
|
|
||||||
|
- for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) {
|
||||||
|
+ for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().realPlayers) { // Leaves - only real players
|
||||||
|
if (predicate.test(serverPlayer1)) {
|
||||||
|
players.add(serverPlayer1);
|
||||||
|
if (players.size() >= resultLimit) {
|
||||||
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
|
index c33757d3e53a97148c11f601cde0b6127d663f11..c67fed7b35f273a2eb6809897a891988fe30558c 100644
|
||||||
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -1805,7 +1805,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerStatus.Players buildPlayerStatus() {
|
||||||
|
- List<ServerPlayer> players = new java.util.ArrayList<>(this.playerList.getPlayers()); // Folia - region threading
|
||||||
|
+ List<ServerPlayer> players = new java.util.ArrayList<>(this.playerList.realPlayers); // Folia - region threading
|
||||||
|
int maxPlayers = this.getMaxPlayers();
|
||||||
|
if (this.hidesOnlinePlayers()) {
|
||||||
|
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
|
||||||
|
@@ -2006,7 +2006,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPlayerCount() {
|
||||||
|
- return this.playerList.getPlayerCount();
|
||||||
|
+ return this.playerList.realPlayers.size(); // Leaves - only real player
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -2420,7 +2420,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
if (Thread.currentThread() != this.serverThread) return; // Paper
|
||||||
|
// Paper start - we don't need to save everything, just advancements
|
||||||
|
// this.getPlayerList().saveAll();
|
||||||
|
- for (final ServerPlayer player : this.getPlayerList().getPlayers()) {
|
||||||
|
+ for (final ServerPlayer player : this.getPlayerList().realPlayers) { // Leaves - only real players
|
||||||
|
player.getAdvancements().save();
|
||||||
|
}
|
||||||
|
// Paper end - we don't need to save everything, just advancements
|
||||||
|
@@ -2559,7 +2559,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
if (!playerList.isUsingWhitelist()) return; // Paper - whitelist not enabled
|
||||||
|
UserWhiteList whiteList = playerList.getWhiteList();
|
||||||
|
|
||||||
|
- for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) {
|
||||||
|
+ for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.realPlayers)) { // Leaves - only real player
|
||||||
|
if (!whiteList.isWhiteListed(serverPlayer.getGameProfile()) && !this.getPlayerList().isOp(serverPlayer.getGameProfile())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420)
|
||||||
|
serverPlayer.connection.disconnect(net.kyori.adventure.text.Component.text(org.spigotmc.SpigotConfig.whitelistMessage), org.bukkit.event.player.PlayerKickEvent.Cause.WHITELIST); // Paper - use configurable message & kick event cause
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java
|
||||||
|
index 5c0e338dc1b0eb5724d10a73d6fc7975f9d2e5e5..0e7e4246837353a5936a6388f23b6b4b2ec1d5f3 100644
|
||||||
|
--- a/net/minecraft/server/PlayerAdvancements.java
|
||||||
|
+++ b/net/minecraft/server/PlayerAdvancements.java
|
||||||
|
@@ -168,7 +168,7 @@ public class PlayerAdvancements {
|
||||||
|
|
||||||
|
public boolean award(AdvancementHolder advancement, String criterionKey) {
|
||||||
|
// Leaves start - bot can't get advancement
|
||||||
|
- if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||||
|
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot || player instanceof org.leavesmc.leaves.replay.ServerPhotographer) { // Leaves - and photographer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Leaves end - bot can't get advancement
|
||||||
|
diff --git a/net/minecraft/server/ServerScoreboard.java b/net/minecraft/server/ServerScoreboard.java
|
||||||
|
index fc1c377ad05edcefacd407671801ae605f3fc31a..5635f0940b4b70f27c8dfdc1aa666fcb7e26d55d 100644
|
||||||
|
--- a/net/minecraft/server/ServerScoreboard.java
|
||||||
|
+++ b/net/minecraft/server/ServerScoreboard.java
|
||||||
|
@@ -242,7 +242,7 @@ public class ServerScoreboard extends Scoreboard {
|
||||||
|
public void startTrackingObjective(Objective objective) {
|
||||||
|
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
|
||||||
|
|
||||||
|
- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
|
||||||
|
+ for (ServerPlayer serverPlayer : this.server.getPlayerList().realPlayers) { // Leaves - only real players
|
||||||
|
if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||||
|
for (Packet<?> packet : startTrackingPackets) {
|
||||||
|
serverPlayer.connection.send(packet);
|
||||||
|
@@ -268,7 +268,7 @@ public class ServerScoreboard extends Scoreboard {
|
||||||
|
public void stopTrackingObjective(Objective objective) {
|
||||||
|
List<Packet<?>> stopTrackingPackets = this.getStopTrackingPackets(objective);
|
||||||
|
|
||||||
|
- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
|
||||||
|
+ for (ServerPlayer serverPlayer : this.server.getPlayerList().realPlayers) { // Leaves - only real players
|
||||||
|
if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board
|
||||||
|
for (Packet<?> packet : stopTrackingPackets) {
|
||||||
|
serverPlayer.connection.send(packet);
|
||||||
|
diff --git a/net/minecraft/server/commands/DefaultGameModeCommands.java b/net/minecraft/server/commands/DefaultGameModeCommands.java
|
||||||
|
index c2ab47bb97c4fbbbc48a8ff0538ab8fd38532a88..2b7d11195f96e68a004e0e060e19d4004bb8a154 100644
|
||||||
|
--- a/net/minecraft/server/commands/DefaultGameModeCommands.java
|
||||||
|
+++ b/net/minecraft/server/commands/DefaultGameModeCommands.java
|
||||||
|
@@ -27,7 +27,7 @@ public class DefaultGameModeCommands {
|
||||||
|
server.setDefaultGameType(gamemode);
|
||||||
|
GameType forcedGameType = server.getForcedGameType();
|
||||||
|
if (forcedGameType != null) {
|
||||||
|
- for (ServerPlayer serverPlayer : server.getPlayerList().getPlayers()) {
|
||||||
|
+ for (ServerPlayer serverPlayer : server.getPlayerList().realPlayers) { // Leaves - only real players
|
||||||
|
serverPlayer.getBukkitEntity().taskScheduler.schedule((ServerPlayer player) -> { // Folia - region threading
|
||||||
|
// Paper start - Expand PlayerGameModeChangeEvent
|
||||||
|
org.bukkit.event.player.PlayerGameModeChangeEvent event = player.setGameMode(gamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty()); // Folia - region threading
|
||||||
|
diff --git a/net/minecraft/server/commands/ListPlayersCommand.java b/net/minecraft/server/commands/ListPlayersCommand.java
|
||||||
|
index c6ae34f91b3629990294fc5e69237a1e600ef038..2109b0a2d4099e64c34cd1c45b83f72654d3b615 100644
|
||||||
|
--- a/net/minecraft/server/commands/ListPlayersCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/ListPlayersCommand.java
|
||||||
|
@@ -33,7 +33,7 @@ public class ListPlayersCommand {
|
||||||
|
private static int format(CommandSourceStack source, Function<ServerPlayer, Component> nameExtractor) {
|
||||||
|
PlayerList playerList = source.getServer().getPlayerList();
|
||||||
|
// CraftBukkit start
|
||||||
|
- List<ServerPlayer> playersTemp = playerList.getPlayers();
|
||||||
|
+ List<ServerPlayer> playersTemp = playerList.realPlayers;
|
||||||
|
if (source.getBukkitSender() instanceof org.bukkit.entity.Player) {
|
||||||
|
org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender();
|
||||||
|
playersTemp = playersTemp.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList());
|
||||||
|
diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java
|
||||||
|
index e6c7bbb023000b9de90c1256274ff5aba4a6478a..98f8804d58616592332e2a968282be6ad8903ea8 100644
|
||||||
|
--- a/net/minecraft/server/commands/OpCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/OpCommand.java
|
||||||
|
@@ -25,7 +25,7 @@ public class OpCommand {
|
||||||
|
(commandContext, suggestionsBuilder) -> {
|
||||||
|
PlayerList playerList = commandContext.getSource().getServer().getPlayerList();
|
||||||
|
return SharedSuggestionProvider.suggest(
|
||||||
|
- playerList.getPlayers()
|
||||||
|
+ playerList.realPlayers // Leaves - only real player
|
||||||
|
.stream()
|
||||||
|
.filter(serverPlayer -> !playerList.isOp(serverPlayer.getGameProfile()))
|
||||||
|
.map(serverPlayer -> serverPlayer.getGameProfile().getName()),
|
||||||
|
diff --git a/net/minecraft/server/commands/ParticleCommand.java b/net/minecraft/server/commands/ParticleCommand.java
|
||||||
|
index 33d96239f4b72a5587dc70f9602847a870d6d6a5..a83ce2cd112fca02cf3545f8c38e5cafae2c7c0e 100644
|
||||||
|
--- a/net/minecraft/server/commands/ParticleCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/ParticleCommand.java
|
||||||
|
@@ -36,7 +36,7 @@ public class ParticleCommand {
|
||||||
|
0.0F,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
- commandContext.getSource().getServer().getPlayerList().getPlayers()
|
||||||
|
+ commandContext.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
@@ -50,7 +50,7 @@ public class ParticleCommand {
|
||||||
|
0.0F,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
- context1.getSource().getServer().getPlayerList().getPlayers()
|
||||||
|
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
@@ -68,7 +68,7 @@ public class ParticleCommand {
|
||||||
|
FloatArgumentType.getFloat(context1, "speed"),
|
||||||
|
IntegerArgumentType.getInteger(context1, "count"),
|
||||||
|
false,
|
||||||
|
- context1.getSource().getServer().getPlayerList().getPlayers()
|
||||||
|
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
@@ -82,7 +82,7 @@ public class ParticleCommand {
|
||||||
|
FloatArgumentType.getFloat(context1, "speed"),
|
||||||
|
IntegerArgumentType.getInteger(context1, "count"),
|
||||||
|
true,
|
||||||
|
- context1.getSource().getServer().getPlayerList().getPlayers()
|
||||||
|
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
@@ -112,7 +112,7 @@ public class ParticleCommand {
|
||||||
|
FloatArgumentType.getFloat(context1, "speed"),
|
||||||
|
IntegerArgumentType.getInteger(context1, "count"),
|
||||||
|
false,
|
||||||
|
- context1.getSource().getServer().getPlayerList().getPlayers()
|
||||||
|
+ context1.getSource().getServer().getPlayerList().realPlayers // Leaves - only real player
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
diff --git a/net/minecraft/server/commands/TeamMsgCommand.java b/net/minecraft/server/commands/TeamMsgCommand.java
|
||||||
|
index 134d7b1a9d5a5a47ebf4aabff110dde914cd6fe1..894dd1d048904b8a775416ea6cb3112215c567bc 100644
|
||||||
|
--- a/net/minecraft/server/commands/TeamMsgCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/TeamMsgCommand.java
|
||||||
|
@@ -40,7 +40,7 @@ public class TeamMsgCommand {
|
||||||
|
} else {
|
||||||
|
List<ServerPlayer> list = commandSourceStack.getServer()
|
||||||
|
.getPlayerList()
|
||||||
|
- .getPlayers()
|
||||||
|
+ .realPlayers // Leaves - only real players
|
||||||
|
.stream()
|
||||||
|
.filter(player -> player == entityOrException || player.getTeam() == team)
|
||||||
|
.toList();
|
||||||
|
diff --git a/net/minecraft/server/commands/WhitelistCommand.java b/net/minecraft/server/commands/WhitelistCommand.java
|
||||||
|
index 763a51d9a0859296eb4ea52b6879d6c7703db673..25b4fcf79dbf3e227451b3321d8fd38bab55ffe9 100644
|
||||||
|
--- a/net/minecraft/server/commands/WhitelistCommand.java
|
||||||
|
+++ b/net/minecraft/server/commands/WhitelistCommand.java
|
||||||
|
@@ -43,7 +43,7 @@ public class WhitelistCommand {
|
||||||
|
(commandContext, suggestionsBuilder) -> {
|
||||||
|
PlayerList playerList = commandContext.getSource().getServer().getPlayerList();
|
||||||
|
return SharedSuggestionProvider.suggest(
|
||||||
|
- playerList.getPlayers()
|
||||||
|
+ playerList.realPlayers // Leaves - only real player
|
||||||
|
.stream()
|
||||||
|
.filter(serverPlayer -> !playerList.getWhiteList().isWhiteListed(serverPlayer.getGameProfile()))
|
||||||
|
.map(serverPlayer -> serverPlayer.getGameProfile().getName()),
|
||||||
|
diff --git a/net/minecraft/server/gui/PlayerListComponent.java b/net/minecraft/server/gui/PlayerListComponent.java
|
||||||
|
index f5ba0c9a4c3f9eaa38eeb689de915c25c7165433..24bbc32bc17802edbd9cc14310fe8141c0ad85b0 100644
|
||||||
|
--- a/net/minecraft/server/gui/PlayerListComponent.java
|
||||||
|
+++ b/net/minecraft/server/gui/PlayerListComponent.java
|
||||||
|
@@ -17,8 +17,8 @@ public class PlayerListComponent extends JList<String> {
|
||||||
|
if (this.tickCount++ % 20 == 0) {
|
||||||
|
Vector<String> list = new Vector<>();
|
||||||
|
|
||||||
|
- for (int i = 0; i < this.server.getPlayerList().getPlayers().size(); i++) {
|
||||||
|
- list.add(this.server.getPlayerList().getPlayers().get(i).getGameProfile().getName());
|
||||||
|
+ for (int i = 0; i < this.server.getPlayerList().realPlayers.size(); i++) { // Leaves - only real players
|
||||||
|
+ list.add(this.server.getPlayerList().realPlayers.get(i).getGameProfile().getName()); // Leaves - only real players
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setListData(list);
|
||||||
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
index 3393fb585747aaf3fa270c4bfe06ed4e9174d519..c58b88f09e6f08d178fcb17a13dd790c3cb62aae 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
@@ -2836,7 +2836,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
|
ServerLevel.this.players.add(serverPlayer);
|
||||||
|
// Leaves start - skip
|
||||||
|
- if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||||
|
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
|
||||||
|
ServerLevel.this.realPlayers.add(serverPlayer);
|
||||||
|
}
|
||||||
|
// Leaves end - skip
|
||||||
|
@@ -2928,7 +2928,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
if (entity instanceof ServerPlayer serverPlayer) {
|
||||||
|
ServerLevel.this.players.remove(serverPlayer);
|
||||||
|
// Leaves start - skip
|
||||||
|
- if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) {
|
||||||
|
+ if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) && !(serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { // and photographer
|
||||||
|
ServerLevel.this.realPlayers.remove(serverPlayer);
|
||||||
|
}
|
||||||
|
// Leaves end - skip
|
||||||
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
index 4b2dba8b30b72fb3acc00957b3e19d6fc178c99e..afd607df83fda3de6f53f55ad305c8f69fe6ddb6 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
@@ -194,7 +194,7 @@ import net.minecraft.world.scores.criteria.ObjectiveCriteria;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
|
||||||
|
- private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
+ protected static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
public static final long LAST_SAVE_ABSENT = Long.MIN_VALUE; public long lastSave = LAST_SAVE_ABSENT; // Paper // Folia - threaded regions - changed to nanoTime
|
||||||
|
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
|
||||||
|
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||||
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||||
|
index 11c1eb6995ec3aa896815efa59477096c39089d1..762728e490a152d159684324e200ab0d2852ac7f 100644
|
||||||
|
--- a/net/minecraft/server/players/PlayerList.java
|
||||||
|
+++ b/net/minecraft/server/players/PlayerList.java
|
||||||
|
@@ -130,6 +130,7 @@ public abstract class PlayerList {
|
||||||
|
private boolean allowCommandsForAllPlayers;
|
||||||
|
private static final boolean ALLOW_LOGOUTIVATOR = false;
|
||||||
|
private int sendAllPlayerInfoIn;
|
||||||
|
+ public final List<ServerPlayer> realPlayers = new java.util.concurrent.CopyOnWriteArrayList(); // Leaves - replay api
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
private org.bukkit.craftbukkit.CraftServer cserver;
|
||||||
|
@@ -213,6 +214,123 @@ public abstract class PlayerList {
|
||||||
|
|
||||||
|
abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor
|
||||||
|
|
||||||
|
+ // Leaves start - replay mod api
|
||||||
|
+ public void placeNewPhotographer(Connection connection, org.leavesmc.leaves.replay.ServerPhotographer player, ServerLevel worldserver) {
|
||||||
|
+ player.isRealPlayer = true; // Paper
|
||||||
|
+ player.loginTime = System.currentTimeMillis(); // Paper
|
||||||
|
+
|
||||||
|
+ ServerLevel worldserver1 = worldserver;
|
||||||
|
+
|
||||||
|
+ player.setServerLevel(worldserver1);
|
||||||
|
+ player.spawnIn(worldserver1);
|
||||||
|
+ player.gameMode.setLevel((ServerLevel) player.level());
|
||||||
|
+
|
||||||
|
+ LevelData worlddata = worldserver1.getLevelData();
|
||||||
|
+
|
||||||
|
+ player.loadGameTypes(null);
|
||||||
|
+ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, CommonListenerCookie.createInitial(player.gameProfile, false));
|
||||||
|
+ GameRules gamerules = worldserver1.getGameRules();
|
||||||
|
+ boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN);
|
||||||
|
+ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
|
||||||
|
+ boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING);
|
||||||
|
+
|
||||||
|
+ playerconnection.send(new ClientboundLoginPacket(player.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), worldserver1.getWorld().getSendViewDistance(), worldserver1.getWorld().getSimulationDistance(), flag1, !flag, flag2, player.createCommonSpawnInfo(worldserver1), this.server.enforceSecureProfile())); // Paper - replace old player chunk management
|
||||||
|
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||||
|
+ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked()));
|
||||||
|
+ playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
|
||||||
|
+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||||
|
+ RecipeManager craftingmanager = this.server.getRecipeManager();
|
||||||
|
+ playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes()));
|
||||||
|
+
|
||||||
|
+ this.sendPlayerPermissionLevel(player);
|
||||||
|
+ player.getStats().markAllDirty();
|
||||||
|
+ player.getRecipeBook().sendInitialRecipeBook(player);
|
||||||
|
+ this.updateEntireScoreboard(worldserver1.getScoreboard(), player);
|
||||||
|
+ this.server.invalidateStatus();
|
||||||
|
+
|
||||||
|
+ playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||||
|
+ ServerStatus serverping = this.server.getStatus();
|
||||||
|
+
|
||||||
|
+ if (serverping != null) {
|
||||||
|
+ player.sendServerStatus(serverping);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this.players.add(player);
|
||||||
|
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||||
|
+ this.playersByUUID.put(player.getUUID(), player);
|
||||||
|
+
|
||||||
|
+ player.supressTrackerForLogin = true;
|
||||||
|
+ worldserver1.getCurrentWorldData().connections.add(player.connection.connection);
|
||||||
|
+ worldserver1.addNewPlayer(player);
|
||||||
|
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||||
|
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
|
||||||
|
+
|
||||||
|
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
|
||||||
|
+ if (!player.connection.isAcceptingMessages()) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
||||||
|
+
|
||||||
|
+ // Leaves start - bot support
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.FakeplayerConfig.enable) {
|
||||||
|
+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName());
|
||||||
|
+ if (bot != null) {
|
||||||
|
+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false);
|
||||||
|
+ }
|
||||||
|
+ this.server.getBotList().bots.forEach(bot1 -> {
|
||||||
|
+ bot1.sendPlayerInfo(player);
|
||||||
|
+ bot1.sendFakeDataIfNeed(player, true);
|
||||||
|
+ }); // Leaves - render bot
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - bot support
|
||||||
|
+
|
||||||
|
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1);
|
||||||
|
+ final List<ServerPlayer> playerList = List.copyOf(this.players); // Lophine - copy to avoid ConcurrentModificationException
|
||||||
|
+ for (ServerPlayer serverPlayer : playerList) {
|
||||||
|
+ if (serverPlayer == player || !bukkitPlayer.canSee(serverPlayer.getBukkitEntity())) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Leaves start - skip photographer
|
||||||
|
+ if (serverPlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - skip photographer
|
||||||
|
+
|
||||||
|
+ onlinePlayers.add(serverPlayer);
|
||||||
|
+ }
|
||||||
|
+ if (!onlinePlayers.isEmpty()) {
|
||||||
|
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ player.sentListPacket = true;
|
||||||
|
+ player.supressTrackerForLogin = false;
|
||||||
|
+ player.level().getChunkSource().chunkMap.addEntity(player);
|
||||||
|
+
|
||||||
|
+ this.sendLevelInfo(player, worldserver1);
|
||||||
|
+
|
||||||
|
+ if (player.level() == worldserver1 && !worldserver1.players().contains(player)) {
|
||||||
|
+ worldserver1.addNewPlayer(player);
|
||||||
|
+ this.server.getCustomBossEvents().onPlayerConnect(player);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ worldserver1 = player.level();
|
||||||
|
+ for (MobEffectInstance mobeffect : player.getActiveEffects()) {
|
||||||
|
+ playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect, false));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (player.isDeadOrDying()) {
|
||||||
|
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = worldserver1.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
|
||||||
|
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
||||||
|
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||||
|
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(worldserver1, player.chunkPosition(), plains),
|
||||||
|
+ worldserver1.getLightEngine(), null, null, false)
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - replay mod api
|
||||||
|
+
|
||||||
|
public void loadSpawnForNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie, org.apache.commons.lang3.mutable.MutableObject<net.minecraft.util.ProblemReporter.ScopedCollector> scopedCollectorStore, org.apache.commons.lang3.mutable.MutableObject<ValueInput> data, org.apache.commons.lang3.mutable.MutableObject<String> lastKnownName, ca.spottedleaf.concurrentutil.completable.CallbackCompletable<org.bukkit.Location> toComplete) { // Folia - region threading - rewrite login process
|
||||||
|
player.isRealPlayer = true; // Paper
|
||||||
|
player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed
|
||||||
|
@@ -398,6 +516,7 @@ public abstract class PlayerList {
|
||||||
|
|
||||||
|
// player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
|
||||||
|
this.players.add(player);
|
||||||
|
+ this.realPlayers.add(player); // Leaves - replay api
|
||||||
|
this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
|
||||||
|
this.playersByUUID.put(player.getUUID(), player);
|
||||||
|
// this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
|
||||||
|
@@ -601,6 +720,7 @@ public abstract class PlayerList {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void save(ServerPlayer player) {
|
||||||
|
+ if (player instanceof org.leavesmc.leaves.replay.ServerPhotographer) return; // Leaves - skip photographer
|
||||||
|
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
|
||||||
|
player.lastSave = System.nanoTime(); // Folia - region threading - changed to nanoTime tracking
|
||||||
|
this.playerIo.save(player);
|
||||||
|
@@ -615,6 +735,44 @@ public abstract class PlayerList {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - replay mod api
|
||||||
|
+ public void removePhotographer(org.leavesmc.leaves.replay.ServerPhotographer entityplayer) {
|
||||||
|
+ ServerLevel worldserver = entityplayer.level();
|
||||||
|
+
|
||||||
|
+ entityplayer.awardStat(Stats.LEAVE_GAME);
|
||||||
|
+
|
||||||
|
+ if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
|
||||||
|
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (server.isSameThread()) entityplayer.doTick();
|
||||||
|
+
|
||||||
|
+ if (this.collideRuleTeamName != null) {
|
||||||
|
+ final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard();
|
||||||
|
+ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName);
|
||||||
|
+ if (entityplayer.getTeam() == team && team != null) {
|
||||||
|
+ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ worldserver.getCurrentWorldData().connections.remove(entityplayer.connection.connection);
|
||||||
|
+ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||||
|
+ entityplayer.retireScheduler();
|
||||||
|
+ entityplayer.getAdvancements().stopListening();
|
||||||
|
+ this.players.remove(entityplayer);
|
||||||
|
+ this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT));
|
||||||
|
+ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer);
|
||||||
|
+ UUID uuid = entityplayer.getUUID();
|
||||||
|
+ ServerPlayer entityplayer1 = this.playersByUUID.get(uuid);
|
||||||
|
+
|
||||||
|
+ if (entityplayer1 == entityplayer) {
|
||||||
|
+ this.playersByUUID.remove(uuid);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
|
||||||
|
+ }
|
||||||
|
+ // Leaves stop - replay mod api
|
||||||
|
+
|
||||||
|
public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component
|
||||||
|
// Paper start - Fix kick event leave message not being sent
|
||||||
|
return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName())));
|
||||||
|
@@ -688,6 +846,7 @@ public abstract class PlayerList {
|
||||||
|
player.retireScheduler(); // Paper - Folia schedulers
|
||||||
|
player.getAdvancements().stopListening();
|
||||||
|
this.players.remove(player);
|
||||||
|
+ this.realPlayers.remove(player); // Leaves - replay api
|
||||||
|
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||||
|
this.server.getCustomBossEvents().onPlayerDisconnect(player);
|
||||||
|
UUID uuid = player.getUUID();
|
||||||
|
@@ -1044,15 +1203,15 @@ public abstract class PlayerList {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getPlayerNamesArray() {
|
||||||
|
- List<ServerPlayer> players = new java.util.ArrayList<>(this.players); // Folia - region threading
|
||||||
|
- String[] strings = new String[this.players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support
|
||||||
|
+ List<ServerPlayer> players = new java.util.ArrayList<>(this.realPlayers); // Folia - region threading
|
||||||
|
+ String[] strings = new String[players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support, and skip photographer
|
||||||
|
|
||||||
|
- for (int i = 0; i < players.size(); i++) { // Folia - region threading
|
||||||
|
- strings[i] = players.get(i).getGameProfile().getName(); // Folia - region threading
|
||||||
|
+ for (int i = 0; i < players.size(); i++) { // Folia - region threading // Leaves - only real players
|
||||||
|
+ strings[i] = players.get(i).getGameProfile().getName(); // Folia - region threading // Leaves - only real players
|
||||||
|
}
|
||||||
|
// Leaves start - fakeplayer support
|
||||||
|
- for (int i = this.players.size(); i < strings.length; ++i) {
|
||||||
|
- strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().getName();
|
||||||
|
+ for (int i = players.size(); i < strings.length; ++i) { // Leaves - only real players
|
||||||
|
+ strings[i] = this.server.getBotList().bots.get(i - players.size()).getGameProfile().getName(); // Leaves - only real players
|
||||||
|
}
|
||||||
|
// Leaves end - fakeplayer support
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
index 12466e0294123a5922ee7694984d4d277a390ddd..205e2648569b7c18f488aa4d3d9ec944bb1babf4 100644
|
||||||
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
@@ -257,7 +257,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||||
|
protected ItemStack useItem = ItemStack.EMPTY;
|
||||||
|
public int useItemRemaining;
|
||||||
|
protected int fallFlyTicks;
|
||||||
|
- private BlockPos lastPos;
|
||||||
|
+ protected BlockPos lastPos;
|
||||||
|
private Optional<BlockPos> lastClimbablePos = Optional.empty();
|
||||||
|
@Nullable
|
||||||
|
private DamageSource lastDamageSource;
|
||||||
+217
@@ -0,0 +1,217 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bacteriawa <A3167717663@hotmail.com>
|
||||||
|
Date: Sat, 15 Nov 2025 01:06:20 +0800
|
||||||
|
Subject: [PATCH] Leaves: Catch update suppression crash
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java
|
||||||
|
index 7280ca2250ade4166a1a883b205bbc89f4e00d1a..06268ac3420fc03a798a20bb617ba89a032df527 100644
|
||||||
|
--- a/net/minecraft/network/protocol/PacketUtils.java
|
||||||
|
+++ b/net/minecraft/network/protocol/PacketUtils.java
|
||||||
|
@@ -30,7 +30,20 @@ public class PacketUtils {
|
||||||
|
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(packet.getClass().getName()))); try { // Folia - profiler
|
||||||
|
packet.handle(processor);
|
||||||
|
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
|
||||||
|
+ exception.providePlayer(gamePacketListener.player);
|
||||||
|
+ }
|
||||||
|
+ exception.consume();
|
||||||
|
} catch (Exception var4) {
|
||||||
|
+ if (var4.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
|
||||||
|
+ exception.providePlayer(gamePacketListener.player);
|
||||||
|
+ }
|
||||||
|
+ exception.consume();
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
if (var4 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) {
|
||||||
|
throw makeReportedException(var4, packet, processor);
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
|
index c67fed7b35f273a2eb6809897a891988fe30558c..1f1e23d9cd73e3ada89367a080de445a18823d7f 100644
|
||||||
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -1883,8 +1883,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
try {
|
||||||
|
profiler.startTimer(serverLevel.tickTimerId); try { // Folia - profiler
|
||||||
|
serverLevel.tick(hasTimeLeft, region); // Folia - region threading
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ exception.provideLevel(serverLevel);
|
||||||
|
+ exception.consume();
|
||||||
|
} finally { profiler.stopTimer(serverLevel.tickTimerId); } // Folia - profiler
|
||||||
|
} catch (Throwable var7) {
|
||||||
|
+ if (var7.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ exception.provideLevel(serverLevel);
|
||||||
|
+ exception.consume();
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
CrashReport crashReport = CrashReport.forThrowable(var7, "Exception ticking world");
|
||||||
|
serverLevel.fillReportDetails(crashReport);
|
||||||
|
throw new ReportedException(crashReport);
|
||||||
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
index c58b88f09e6f08d178fcb17a13dd790c3cb62aae..c0ba36849da0983117901f0cd04b2c785df0010b 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
@@ -840,7 +840,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
// Kaiiju end
|
||||||
|
|
||||||
|
profilerFiller.push("tick");
|
||||||
|
- this.guardEntityTick(this::tickNonPassenger, entity);
|
||||||
|
+ // Lophine start - update suppression crash fix
|
||||||
|
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
+ try {
|
||||||
|
+ this.tickNonPassenger(entity); // Lophine changed
|
||||||
|
+ // Leaves start - update suppression crash fix - for dragon dupe
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ exception.provideLevel(this);
|
||||||
|
+ exception.consume();
|
||||||
|
+ // Leaves end - update suppression crash fix - for dragon dupe
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ this.guardEntityTick(this::tickNonPassenger, entity);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - update suppression crash fix
|
||||||
|
profilerFiller.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
index afd607df83fda3de6f53f55ad305c8f69fe6ddb6..e2f4b35c88c64a68cf7ef9fadf977e7b99e17c6e 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
@@ -1123,6 +1123,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||||
|
((org.bukkit.craftbukkit.CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick();
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ exception.providePlayer(this);
|
||||||
|
+ exception.provideLevel(this.level());
|
||||||
|
+ exception.consume();
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
} catch (Throwable var4) {
|
||||||
|
CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player");
|
||||||
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked");
|
||||||
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
|
index 477241699752567df7695d33fa629fb1d5109e0a..f63252c580c313ccf89304866cfc6503f4b26052 100644
|
||||||
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
|
@@ -1403,9 +1403,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
|
this.walkingStepSound(pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
if (broadcastGameEvent) {
|
||||||
|
- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, state));
|
||||||
|
+ try {
|
||||||
|
+ this.level().gameEvent(net.minecraft.world.level.gameevent.GameEvent.STEP, this.position(), net.minecraft.world.level.gameevent.GameEvent.Context.of(this, state));
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
|
||||||
|
+ exception.provideBlock(level, pos, state.getBlock());
|
||||||
|
+ if (this instanceof net.minecraft.server.level.ServerPlayer player) {
|
||||||
|
+ exception.providePlayer(player);
|
||||||
|
+ }
|
||||||
|
+ exception.consume();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
index 49bac7af90b0a7c490141be6357563447783c6ca..a26cd86aedcaf7ab606f8543e08360cbe9f2d1e6 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
@@ -183,7 +183,17 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||||
|
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ try {
|
||||||
|
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||||
|
+ } catch (ClassCastException ex) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
|
||||||
|
+ } else {
|
||||||
|
+ throw ex;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Block getBlockByColor(@Nullable DyeColor color) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/state/StateHolder.java b/net/minecraft/world/level/block/state/StateHolder.java
|
||||||
|
index 9b9842462b210b0407279ee8a8e9ccecf3ead005..1057f3bd32ff4c8f93f09251341c243915593e4d 100644
|
||||||
|
--- a/net/minecraft/world/level/block/state/StateHolder.java
|
||||||
|
+++ b/net/minecraft/world/level/block/state/StateHolder.java
|
||||||
|
@@ -104,7 +104,16 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
|
||||||
|
if (ret != null) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
|
||||||
|
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
+ org.leavesmc.leaves.util.UpdateSuppressionException exception = new org.leavesmc.leaves.util.UpdateSuppressionException(null, null, null, null, iae);
|
||||||
|
+ if (exception.getStackTrace()[1].getClassName().startsWith("net.minecraft")) {
|
||||||
|
+ throw exception;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ throw iae;
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
// Paper end - optimise blockstate property access
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
index 1f44a59e46f86ca055e89631d831a38f4c3e238e..39c075173b77b5197af5d4ad3fe235ea0d2df756 100644
|
||||||
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
@@ -378,7 +378,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||||
|
if (blockState == state) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
- Block block = state.getBlock();
|
||||||
|
+ Block block = state.getBlock(); try { // Leaves start - update suppression crash fix
|
||||||
|
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state);
|
||||||
|
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state);
|
||||||
|
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state);
|
||||||
|
@@ -450,6 +450,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||||
|
this.markUnsaved();
|
||||||
|
return blockState;
|
||||||
|
}
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) { e.provideBlock(level, pos, block); throw e; } // Leaves - update suppression crash fix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||||
|
index 714e291b17856aacdac7db992fc18e6ae662f659..01285691a2e0bf72b94969e9045f7ab42a9161bf 100644
|
||||||
|
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||||
|
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||||
|
@@ -63,9 +63,22 @@ public interface NeighborUpdater {
|
||||||
|
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
|
||||||
|
// Spigot start
|
||||||
|
} catch (StackOverflowError ex) {
|
||||||
|
+ // Leaves start - update suppression crash fix
|
||||||
|
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, ex);
|
||||||
|
+ }
|
||||||
|
level.lastPhysicsProblem = pos.immutable();
|
||||||
|
// Spigot end
|
||||||
|
} catch (Throwable var9) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException ue) {
|
||||||
|
+ ue.provideBlock(level, pos, neighborBlock);
|
||||||
|
+ throw ue;
|
||||||
|
+ } else {
|
||||||
|
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, var9);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - update suppression crash fix
|
||||||
|
CrashReport crashReport = CrashReport.forThrowable(var9, "Exception while updating neighbours");
|
||||||
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Block being updated");
|
||||||
|
crashReportCategory.setDetail(
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bacteriawa <A3167717663@hotmail.com>
|
||||||
|
Date: Sat, 15 Nov 2025 01:12:39 +0800
|
||||||
|
Subject: [PATCH] Leaves: CCE update suppression
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
index a26cd86aedcaf7ab606f8543e08360cbe9f2d1e6..27ccce4b4d8b4cb8be48bfe5d55366abe4ea3a38 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
@@ -185,7 +185,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||||
|
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||||
|
// Leaves start - update suppression crash fix
|
||||||
|
try {
|
||||||
|
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||||
|
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce ?
|
||||||
|
+ AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container) level.getBlockEntity(pos)) : // Leaves - make cce happy(?)
|
||||||
|
+ AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
|
||||||
|
} catch (ClassCastException ex) {
|
||||||
|
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
|
||||||
|
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
Date: Wed, 14 Jun 2023 12:07:07 +0800
|
||||||
|
Subject: [PATCH] Leaves: Redstone ignore upwards update
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
|
||||||
|
index afecf6bb6152b4d9dfee4cd8c5b1d798cbf723b3..a5bbe83b079276a3ab497e8a725713721db83aa1 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ComparatorBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
|
||||||
|
@@ -58,6 +58,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
|
||||||
|
BlockState neighborState,
|
||||||
|
RandomSource random
|
||||||
|
) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
|
||||||
|
return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)
|
||||||
|
? Blocks.AIR.defaultBlockState()
|
||||||
|
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
|
||||||
|
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
index 4b37335e91a51b9a58ce0bce94b61ab5afbc6486..555a00e402da3d9126925135d030b7bccd8e5327 100644
|
||||||
|
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
@@ -179,7 +179,7 @@ public class RedStoneWireBlock extends Block {
|
||||||
|
RandomSource random
|
||||||
|
) {
|
||||||
|
if (direction == Direction.DOWN) {
|
||||||
|
- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state;
|
||||||
|
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19
|
||||||
|
} else if (direction == Direction.UP) {
|
||||||
|
return this.getConnectionState(level, state, pos);
|
||||||
|
} else {
|
||||||
|
@@ -239,7 +239,7 @@ public class RedStoneWireBlock extends Block {
|
||||||
|
BlockPos blockPos = pos.relative(direction);
|
||||||
|
BlockState blockState = level.getBlockState(blockPos);
|
||||||
|
if (nonNormalCubeAbove) {
|
||||||
|
- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState);
|
||||||
|
+ boolean flag = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19
|
||||||
|
if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) {
|
||||||
|
if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) {
|
||||||
|
return RedstoneSide.UP;
|
||||||
|
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
|
||||||
|
index 1d45564253258eebdf10470dd7eefa644a4151ae..4b8a0f7353984d8997ab3b702227ae8d46863d7e 100644
|
||||||
|
--- a/net/minecraft/world/level/block/RepeaterBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
|
||||||
|
@@ -68,6 +68,7 @@ public class RepeaterBlock extends DiodeBlock {
|
||||||
|
BlockState neighborState,
|
||||||
|
RandomSource random
|
||||||
|
) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
|
||||||
|
if (direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)) {
|
||||||
|
return Blocks.AIR.defaultBlockState();
|
||||||
|
} else {
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Mon, 17 Nov 2025 18:41:08 +0800
|
||||||
|
Subject: [PATCH] Instant Block Updater
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
index d0de3b22f6cef6eb213b7ff688a514a67f84fbcf..3b39b8f7ccb278cf910e3cc4e00da29790465a81 100644
|
||||||
|
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
@@ -524,7 +524,7 @@ public final class RegionizedWorldData {
|
||||||
|
this.world = world;
|
||||||
|
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
|
||||||
|
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
|
||||||
|
- this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
|
||||||
|
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world) : new CollectingNeighborUpdater(world, world.neighbourUpdateMax); // Lophine - Instant Block Updater
|
||||||
|
this.nearbyPlayers = new NearbyPlayers(world);
|
||||||
|
this.wireHandler = new alternate.current.wire.WireHandler(world);
|
||||||
|
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Tue, 18 Nov 2025 00:24:32 +0800
|
||||||
|
Subject: [PATCH] Revert TrapDoorBlock changes form paperMC
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/block/TrapDoorBlock.java b/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||||
|
index a2140d22dc58aa2df1afbeb5170d04fd65739d55..ea79c471c03b6908710d5943f2ff378eaba4099e 100644
|
||||||
|
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
|
||||||
|
@@ -128,37 +128,7 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
|
||||||
|
if (!level.isClientSide) {
|
||||||
|
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
|
||||||
|
if (hasNeighborSignal != state.getValue(POWERED)) {
|
||||||
|
- // CraftBukkit start
|
||||||
|
- org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||||
|
- int power = bblock.getBlockPower();
|
||||||
|
- int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
|
||||||
|
-
|
||||||
|
- if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
|
||||||
|
- org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
|
||||||
|
- level.getCraftServer().getPluginManager().callEvent(eventRedstone);
|
||||||
|
- hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
|
||||||
|
- }
|
||||||
|
- // CraftBukkit end
|
||||||
|
- // Paper start - break redstone on trapdoors early
|
||||||
|
- boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
|
||||||
|
- // note: this must run before any state for this block/its neighbours are written to the world
|
||||||
|
- // we allow the redstone event to fire so that plugins can block
|
||||||
|
- if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
|
||||||
|
- // in this case, first check for the redstone on top first
|
||||||
|
- BlockPos abovePos = pos.above();
|
||||||
|
- BlockState above = level.getBlockState(abovePos);
|
||||||
|
- if (above.getBlock() instanceof RedStoneWireBlock) {
|
||||||
|
- level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
|
||||||
|
- Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
|
||||||
|
- // now check that this didn't change our state
|
||||||
|
- if (level.getBlockState(pos) != state) {
|
||||||
|
- // our state was changed, so we cannot propagate this update
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (open) {
|
||||||
|
- // Paper end - break redstone on trapdoors early
|
||||||
|
+ if (state.getValue(OPEN) != hasNeighborSignal) {
|
||||||
|
state = state.setValue(OPEN, hasNeighborSignal);
|
||||||
|
this.playSound(null, level, pos, hasNeighborSignal);
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Tue, 18 Nov 2025 00:35:13 +0800
|
||||||
|
Subject: [PATCH] Leaves: Prevent loss of item drops due to update suppression
|
||||||
|
when breaking blocks
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||||
|
index ee7bdc3adbeb04cf6ca630282f31a21e52bdb215..58f6c3e83c80b4b419ba22da81a7880be5b5d551 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||||
|
@@ -369,7 +369,18 @@ public class ServerPlayerGameMode {
|
||||||
|
this.level.getCurrentWorldData().captureDrops = new java.util.ArrayList<>(); // Folia - region threading
|
||||||
|
// CraftBukkit end
|
||||||
|
BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player);
|
||||||
|
- boolean flag = this.level.removeBlock(pos, false);
|
||||||
|
+ // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks
|
||||||
|
+ boolean flag;
|
||||||
|
+ org.leavesmc.leaves.util.UpdateSuppressionException ex = null;
|
||||||
|
+ try {
|
||||||
|
+ flag = this.level.removeBlock(pos, false);
|
||||||
|
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) {
|
||||||
|
+ ex = e;
|
||||||
|
+ ex.provideBlock(level, pos, block);
|
||||||
|
+ ex.providePlayer(this.player);
|
||||||
|
+ flag = false;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - Prevent loss of item drops due to update suppression when breaking blocks
|
||||||
|
if (flag) {
|
||||||
|
block.destroy(this.level, pos, blockState1);
|
||||||
|
}
|
||||||
|
@@ -397,6 +408,7 @@ public class ServerPlayerGameMode {
|
||||||
|
if (event.isDropItems()) {
|
||||||
|
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
|
||||||
|
}
|
||||||
|
+ if (ex != null) throw ex; // Leaves - Prevent loss of item drops due to update suppression when breaking blocks
|
||||||
|
|
||||||
|
// Drop event experience
|
||||||
|
if (flag) {
|
||||||
+807
@@ -0,0 +1,807 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Tue, 18 Nov 2025 23:11:26 +0800
|
||||||
|
Subject: [PATCH] Leaves: Old Block remove behaviour
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java
|
||||||
|
index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644
|
||||||
|
--- a/net/minecraft/world/Containers.java
|
||||||
|
+++ b/net/minecraft/world/Containers.java
|
||||||
|
@@ -51,4 +51,15 @@ public class Containers {
|
||||||
|
public static void updateNeighboursAfterDestroy(BlockState state, Level level, BlockPos pos) {
|
||||||
|
level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (level.getBlockEntity(pos) instanceof Container container) {
|
||||||
|
+ dropContents(level, pos, container);
|
||||||
|
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||||
|
index d52eeff0d564a24bddb873750c81e3fe999f16f0..aa2597d825f93b0b0623ab7fae29e45de3f3ebcc 100644
|
||||||
|
--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
|
||||||
|
@@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
|
||||||
|
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
+ if (blockEntity instanceof AbstractFurnaceBlockEntity) {
|
||||||
|
+ if (level instanceof ServerLevel) {
|
||||||
|
+ Containers.dropContents(level, pos, (AbstractFurnaceBlockEntity)blockEntity);
|
||||||
|
+ ((AbstractFurnaceBlockEntity)blockEntity).getRecipesToAwardAndPopExperience((ServerLevel)level, net.minecraft.world.phys.Vec3.atCenterOf(pos));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ level.updateNeighbourForOutputSignal(pos, this);
|
||||||
|
+ } else {
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
|
||||||
|
index f7820265f10b78674acd13e6204b9212fd27b038..700bd0f6a4f4fd6cd85b3e666fff1b3fd0a96b8e 100644
|
||||||
|
--- a/net/minecraft/world/level/block/BarrelBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/BarrelBlock.java
|
||||||
|
@@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock {
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||||
|
index 42ee3f32fe44c1f0680c994a69201f7bd7792673..19214c236bca4e454e3bbe7dc50e00b66398c119 100644
|
||||||
|
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
|
||||||
|
@@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ if (this.getSignalForState(state) > 0) {
|
||||||
|
+ this.updateNeighbours(level, pos);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston && this.getSignalForState(state) > 0) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
|
||||||
|
index 5f99e18244501ed2d85be77b71f48cc93058cdb7..6bf50d9c3921b15f40b4fba273abeb4c2e0f30b3 100644
|
||||||
|
--- a/net/minecraft/world/level/block/BaseRailBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
|
||||||
|
@@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving) {
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ if (state.getValue(this.getShapeProperty()).isSlope()) {
|
||||||
|
+ level.updateNeighborsAt(pos.above(), this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (this.isStraight) {
|
||||||
|
+ level.updateNeighborsAt(pos, this);
|
||||||
|
+ level.updateNeighborsAt(pos.below(), this);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||||
|
index f563f8ea63e67f808802baa4c6a700e803c045a0..0cc4479d9d3f6aea280c9f88997d141dc24917a9 100644
|
||||||
|
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||||
|
@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock {
|
||||||
|
level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
|
||||||
|
index 66c589bc633d32ebf36b1ab55ba6250ca2ddd6f6..f96d3c7b7ec15973aca3aabe056608fd5efb856b 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ButtonBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ButtonBlock.java
|
||||||
|
@@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
|
||||||
|
return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ if (state.getValue(POWERED)) {
|
||||||
|
+ this.updateNeighbours(state, level, pos);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston && state.getValue(POWERED)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
|
||||||
|
index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..c9e2becc0644de707e0bd251318813c50fc82be2 100644
|
||||||
|
--- a/net/minecraft/world/level/block/CampfireBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/CampfireBlock.java
|
||||||
|
@@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
|
||||||
|
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
+ if (blockEntity instanceof CampfireBlockEntity) {
|
||||||
|
+ net.minecraft.world.Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
|
||||||
|
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
|
||||||
|
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
|
||||||
|
index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..818b1a5df0e9a0566210e4b3512ad856515e385f 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ChestBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ChestBlock.java
|
||||||
|
@@ -244,6 +244,14 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
|
||||||
|
return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||||
|
index eb315a50a83dc7230d7ad66f4daeb0d632679941..7bccf15310f6851875bfd77d4c66f4ce863b65e1 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
|
||||||
|
@@ -180,6 +180,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock {
|
||||||
|
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (level.getBlockEntity(pos) instanceof ChiseledBookShelfBlockEntity chiseledBookShelfBlockEntity && !chiseledBookShelfBlockEntity.isEmpty()) {
|
||||||
|
+ for (int i = 0; i < 6; i++) {
|
||||||
|
+ ItemStack item = chiseledBookShelfBlockEntity.getItem(i);
|
||||||
|
+ if (!item.isEmpty()) {
|
||||||
|
+ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), item);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ chiseledBookShelfBlockEntity.clearContent();
|
||||||
|
+ level.updateNeighbourForOutputSignal(pos, this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
|
||||||
|
index caf31218a1aff84367da126ee1dc46b8c8a1e5d1..59272e7223aff61d44c86776091ca74891839a45 100644
|
||||||
|
--- a/net/minecraft/world/level/block/CrafterBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/CrafterBlock.java
|
||||||
|
@@ -129,6 +129,14 @@ public class CrafterBlock extends BaseEntityBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||||
|
index 73885449a3316face50292756de2a3f298d3d111..333e18e4ead0bb6ef9681ce27ec156f79821af7c 100644
|
||||||
|
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
|
||||||
|
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
|
||||||
|
builder.add(AXIS, STATE, NATURAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ if (level.getBlockEntity(pos) instanceof CreakingHeartBlockEntity creakingHeartBlockEntity) {
|
||||||
|
+ creakingHeartBlockEntity.removeProtector(null);
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||||
|
index f1570f1f4f7e43aacbcffef8bcf8ef27d46899da..6afd1c618112234ce4940105582a4399e20ab34c 100644
|
||||||
|
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
|
||||||
|
@@ -165,6 +165,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
|
||||||
|
return new DecoratedPotBlockEntity(pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
|
||||||
|
index 0ab376b4207b695e92c324b8a5f9818d3f4accde..bcceb8f17294fb9f275ab6b3a28c75cb423394f2 100644
|
||||||
|
--- a/net/minecraft/world/level/block/DiodeBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/DiodeBlock.java
|
||||||
|
@@ -176,6 +176,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
|
||||||
|
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ this.updateNeighborsInFront(level, pos, state);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
index 7ff6255fcd50344cd6ac7f8a67d61fd59c85e413..7a23d27ce76ae6b90d01c4dc7af416bb6b6516ea 100644
|
||||||
|
--- a/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/DispenserBlock.java
|
||||||
|
@@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock {
|
||||||
|
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
|
||||||
|
index 912d1ba98809b4469e1468e4855bb1bc91bb4540..0f2b344b385b7726c3c23b68da8a2329180fe034 100644
|
||||||
|
--- a/net/minecraft/world/level/block/HopperBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/HopperBlock.java
|
||||||
|
@@ -137,6 +137,14 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
|
||||||
|
index 56cf6528f0cd9b8528490d7cee9a1f0e54108ef9..955854e5b3a18b8f1441145554a97c5454a65d12 100644
|
||||||
|
--- a/net/minecraft/world/level/block/JukeboxBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/JukeboxBlock.java
|
||||||
|
@@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (level.getBlockEntity(pos) instanceof JukeboxBlockEntity jukeboxBlockEntity) {
|
||||||
|
+ jukeboxBlockEntity.popOutTheItem();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
|
||||||
|
index 5a9b601b7bf7e80b04ebd8f5c8b7d121031132c7..b714d3c7649384a8fdbe0a713e2193e241c80618 100644
|
||||||
|
--- a/net/minecraft/world/level/block/LecternBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/LecternBlock.java
|
||||||
|
@@ -197,6 +197,36 @@ public class LecternBlock extends BaseEntityBlock {
|
||||||
|
changePowered(level, pos, state, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (state.getValue(HAS_BOOK)) {
|
||||||
|
+ this.popBook(state, level, pos);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (state.getValue(POWERED)) {
|
||||||
|
+ updateBelow(level, pos, state);
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void popBook(BlockState state, Level level, BlockPos pos) {
|
||||||
|
+ if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already // Leaves - the method with validate arg already removed by paper...
|
||||||
|
+ Direction direction = state.getValue(FACING);
|
||||||
|
+ ItemStack itemStack = lecternBlockEntity.getBook().copy();
|
||||||
|
+ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
|
||||||
|
+ float f = 0.25F * direction.getStepX();
|
||||||
|
+ float f1 = 0.25F * direction.getStepZ();
|
||||||
|
+ net.minecraft.world.entity.item.ItemEntity itemEntity = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack);
|
||||||
|
+ itemEntity.setDefaultPickUpDelay();
|
||||||
|
+ level.addFreshEntity(itemEntity);
|
||||||
|
+ lecternBlockEntity.clearContent();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (state.getValue(POWERED)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
|
||||||
|
index 76f2a29f37187344324d68941307d58e6343b6ae..3645ca9589aa1a74134180c9918a6f67bc64ce7a 100644
|
||||||
|
--- a/net/minecraft/world/level/block/LeverBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/LeverBlock.java
|
||||||
|
@@ -125,6 +125,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ if (state.getValue(POWERED)) {
|
||||||
|
+ this.updateNeighbours(state, level, pos);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston && state.getValue(POWERED)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
|
||||||
|
index d702d234111c2a34585f3532b5bb4bdb1501b82a..d9bedb99590a860a7ebb1d68861dc175ca3f4a2b 100644
|
||||||
|
--- a/net/minecraft/world/level/block/LightningRodBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
|
||||||
|
@@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (state.getValue(POWERED)) {
|
||||||
|
+ this.updateNeighbours(state, level, pos);
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (state.getValue(POWERED)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
|
||||||
|
index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..6db3a21bcc37ae79f82b19ee0a851f539d4a654d 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ObserverBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ObserverBlock.java
|
||||||
|
@@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
|
||||||
|
+ this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.FALSE));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
index 555a00e402da3d9126925135d030b7bccd8e5327..20cec51bcead34f95ed6195a7762cea7ce280914 100644
|
||||||
|
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||||
|
@@ -369,6 +369,27 @@ public class RedStoneWireBlock extends Block {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ for (Direction direction : Direction.values()) {
|
||||||
|
+ level.updateNeighborsAt(pos.relative(direction), this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Paper start - optimize redstone - replace call to updatePowerStrength
|
||||||
|
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
|
||||||
|
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
|
||||||
|
+ } else {
|
||||||
|
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
|
||||||
|
+ }
|
||||||
|
+ // Paper end - optimize redstone
|
||||||
|
+ this.updateNeighborsOfNeighboringWires(level, pos);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||||
|
index df4f1b18deb8bb4a04e740bbbeb6a89cb1ff8e71..7f165a4e2935cf4638b14379a0d1aca1b65ef84a 100644
|
||||||
|
--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java
|
||||||
|
@@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving) {
|
||||||
|
+ this.notifyNeighbors(level, pos, state);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||||
|
index f0101e88140f480c1a94f899744991f78c9e3756..fa9cb4c40a41eea7fd63a4513d0b0f39067de9ba 100644
|
||||||
|
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
|
||||||
|
@@ -129,6 +129,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ if (getPhase(state) == SculkSensorPhase.ACTIVE) {
|
||||||
|
+ updateNeighbours(level, pos, state);
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||||
|
index 757f8453e147875ab9f14d9726bb734ef27447c9..d0558d0e33f3d6e25af2dd71650d723e8997dae6 100644
|
||||||
|
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
|
||||||
|
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
|
||||||
|
super.stepOn(level, pos, state, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) {
|
||||||
|
+ serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel));
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||||
|
if (state.getValue(SHRIEKING)) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
index 27ccce4b4d8b4cb8be48bfe5d55366abe4ea3a38..2e6d462fb27ad1e538164934417ce07cc0e603c2 100644
|
||||||
|
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||||
|
@@ -152,6 +152,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||||
|
// Paper end - re-set loot table if it was cleared
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
+ if (blockEntity instanceof ShulkerBoxBlockEntity) {
|
||||||
|
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
|
||||||
|
+ }
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
Containers.updateNeighboursAfterDestroy(state, level, pos);
|
||||||
|
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
|
||||||
|
index c8f793d1cdeef7e3e0d5fceb45a4507d542e4b33..27f382f6c663b2954a6fb966ece05ba021fcd6b1 100644
|
||||||
|
--- a/net/minecraft/world/level/block/TripWireBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/TripWireBlock.java
|
||||||
|
@@ -108,6 +108,16 @@ public class TripWireBlock extends Block {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
|
||||||
|
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||||
|
index 3f412b08e7d40d577efb7be291dd14826ba21f0e..30c65a0906646fc12cd842336ec4f3e2aaf31717 100644
|
||||||
|
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||||
|
@@ -245,6 +245,25 @@ public class TripWireHookBlock extends Block {
|
||||||
|
level.updateNeighborsAt(pos.relative(opposite), block, orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!isMoving && !state.is(newState.getBlock())) {
|
||||||
|
+ boolean attachedValue = state.getValue(ATTACHED);
|
||||||
|
+ boolean poweredValue = state.getValue(POWERED);
|
||||||
|
+ if (attachedValue || poweredValue) {
|
||||||
|
+ calculateState(level, pos, state, true, false, -1, null);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (poweredValue) {
|
||||||
|
+ notifyNeighbors(this, level, pos, state.getValue(FACING));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
if (!movedByPiston) {
|
||||||
|
diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||||
|
index 7b8631abf8adcdb889d412b30eca10faf044032a..13134dfe9f548b87fd6be4683bf3386c522aba6a 100644
|
||||||
|
--- a/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||||
|
+++ b/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||||
|
@@ -267,7 +267,7 @@ public class BlockEntityType<T extends BlockEntity> {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid(BlockState state) {
|
||||||
|
- return this.validBlocks.contains(state.getBlock());
|
||||||
|
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour || this.validBlocks.contains(state.getBlock()); // Leaves - behaviour 1.21.1-
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||||
|
index 05bbc2e59384702439548a988e128a85f1adbe82..af516d5b6bd31de2c6a388ec8001126e2a351cf3 100644
|
||||||
|
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
|
||||||
|
@@ -67,6 +67,18 @@ public class MovingPistonBlock extends BaseEntityBlock {
|
||||||
|
return createTickerHelper(blockEntityType, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||||
|
+ if (blockEntity instanceof PistonMovingBlockEntity) {
|
||||||
|
+ ((PistonMovingBlockEntity)blockEntity).finalTick();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public void destroy(LevelAccessor level, BlockPos pos, BlockState state) {
|
||||||
|
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||||
|
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||||
|
index 6c789e56f21f01252c21786cfeb48d88485b5636..e24a61a4e2dac0159d52f07c93ddf860f4bfb8f7 100644
|
||||||
|
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||||
|
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
|
||||||
|
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
|
||||||
|
return super.playerWillDestroy(level, pos, state, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ @Override
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
+ if (!state.is(newState.getBlock())) {
|
||||||
|
+ super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
+ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||||
|
+ if (this.isFittingBase(state, level.getBlockState(blockPos))) {
|
||||||
|
+ level.destroyBlock(blockPos, true);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
|
||||||
|
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||||
|
index e9749b66239d7562ecf22002bfbaa95df197050f..6e3841ed012eee16dcaa61f70edfc1d870374a56 100644
|
||||||
|
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||||
|
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||||
|
@@ -172,6 +172,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
|
||||||
|
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
|
||||||
|
+ if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
|
||||||
|
+ level.removeBlockEntity(pos);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -868,6 +877,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
|
+ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston);
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
+
|
||||||
|
public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) {
|
||||||
|
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
index 39c075173b77b5197af5d4ad3fe235ea0d2df756..b8a2ac505d121b46c33db2fbf4d02c5bc60c6c0f 100644
|
||||||
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
@@ -401,20 +401,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||||
|
boolean flag = !blockState.is(block);
|
||||||
|
boolean flag1 = (flags & 64) != 0;
|
||||||
|
boolean flag2 = (flags & 256) == 0;
|
||||||
|
- if (flag && blockState.hasBlockEntity()) {
|
||||||
|
- if (!this.level.isClientSide && flag2) {
|
||||||
|
- BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||||
|
- if (blockEntity != null) {
|
||||||
|
- blockEntity.preRemoveSideEffects(pos, blockState);
|
||||||
|
+ // Leaves start - behaviour 1.21.1-
|
||||||
|
+ if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) {
|
||||||
|
+ if (flag && blockState.hasBlockEntity()) {
|
||||||
|
+ if (!this.level.isClientSide && flag2) {
|
||||||
|
+ BlockEntity blockEntity = this.level.getBlockEntity(pos);
|
||||||
|
+ if (blockEntity != null) {
|
||||||
|
+ blockEntity.preRemoveSideEffects(pos, blockState);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
|
||||||
|
- this.removeBlockEntity(pos);
|
||||||
|
- }
|
||||||
|
+ this.removeBlockEntity(pos);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) {
|
||||||
|
- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
|
||||||
|
+ if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) {
|
||||||
|
+ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ blockState.onRemove(this.level, pos, state, flag1);
|
||||||
|
}
|
||||||
|
+ // Leaves end - behaviour 1.21.1-
|
||||||
|
|
||||||
|
if (!section.getBlockState(i, i1, i2).is(block)) {
|
||||||
|
return null;
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Tue, 18 Nov 2025 23:26:27 +0800
|
||||||
|
Subject: [PATCH] Leaves: Do not reset placed block on exception & Do not
|
||||||
|
prevent block entity and entity crash at LevelChunk
|
||||||
|
|
||||||
|
Co-authored by: MC_XiaoHei <xiaohei.xor7@outlook.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
|
||||||
|
index 8f112f382190d606a87f38da8bcdf8dd5f31d1c5..f27915e43df8e627000cda1cb213a95300c98038 100644
|
||||||
|
--- a/net/minecraft/world/item/BlockItem.java
|
||||||
|
+++ b/net/minecraft/world/item/BlockItem.java
|
||||||
|
@@ -77,20 +77,22 @@ public class BlockItem extends Item {
|
||||||
|
BlockState blockState = level.getBlockState(clickedPos);
|
||||||
|
if (blockState.is(placementState.getBlock())) {
|
||||||
|
blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState);
|
||||||
|
+ // Leaves start - we do not need this
|
||||||
|
// Paper start - Reset placed block on exception
|
||||||
|
- try {
|
||||||
|
+ // try {
|
||||||
|
this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState);
|
||||||
|
updateBlockEntityComponents(level, clickedPos, itemInHand);
|
||||||
|
- } catch (Exception ex) {
|
||||||
|
- ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
|
||||||
|
- if (player instanceof ServerPlayer serverPlayer) {
|
||||||
|
- org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
|
||||||
|
- serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
|
||||||
|
- return InteractionResult.FAIL;
|
||||||
|
- }
|
||||||
|
- throw ex; // Rethrow exception if not placed by a player
|
||||||
|
- }
|
||||||
|
+ // } catch (Exception ex) {
|
||||||
|
+ // ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
|
||||||
|
+ // if (player instanceof ServerPlayer serverPlayer) {
|
||||||
|
+ // org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
|
||||||
|
+ // serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
|
||||||
|
+ // return InteractionResult.FAIL;
|
||||||
|
+ // }
|
||||||
|
+ // throw ex; // Rethrow exception if not placed by a player
|
||||||
|
+ // }
|
||||||
|
// Paper end - Reset placed block on exception
|
||||||
|
+ // Leaves end - we dot not need this
|
||||||
|
blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand);
|
||||||
|
// CraftBukkit start
|
||||||
|
if (bukkitState != null) {
|
||||||
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
index b8a2ac505d121b46c33db2fbf4d02c5bc60c6c0f..7a8ceb00eb5845a1d5011a518f63a9cabf131f3c 100644
|
||||||
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||||
|
@@ -971,12 +971,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||||
|
|
||||||
|
profilerFiller.pop();
|
||||||
|
} catch (Throwable var5) {
|
||||||
|
+ // Leaves start - do not prevent here
|
||||||
|
// Paper start - Prevent block entity and entity crashes
|
||||||
|
- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
|
||||||
|
- net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
|
||||||
|
- net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
|
||||||
|
- LevelChunk.this.removeBlockEntity(this.getPos());
|
||||||
|
+ // final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
|
||||||
|
+ // net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
|
||||||
|
+ // net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
|
||||||
|
+ // LevelChunk.this.removeBlockEntity(this.getPos());
|
||||||
|
// Paper end - Prevent block entity and entity crashes
|
||||||
|
+ // Leaves end - do not prevent here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 3 Dec 2025 16:28:34 +0800
|
||||||
|
Subject: [PATCH] Global Entities Counter
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
index 3b39b8f7ccb278cf910e3cc4e00da29790465a81..7cc41630a39c1e29840d70eee78473d06b7c11cd 100644
|
||||||
|
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
@@ -520,6 +520,9 @@ public final class RegionizedWorldData {
|
||||||
|
public final Map<Long, ChunkSectionItemEntityMovementTracker> itemEntityMovementTrackerMap = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>();
|
||||||
|
// Luminol end
|
||||||
|
|
||||||
|
+ public int uniqueId = -1; // Lophine - Global Entities Counter
|
||||||
|
+ public boolean underGlobalEntitiesCounter = false; // Lophine - Global Entities Counter
|
||||||
|
+
|
||||||
|
public RegionizedWorldData(final ServerLevel world) {
|
||||||
|
this.world = world;
|
||||||
|
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
|
||||||
|
@@ -529,6 +532,15 @@ public final class RegionizedWorldData {
|
||||||
|
this.wireHandler = new alternate.current.wire.WireHandler(world);
|
||||||
|
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
|
||||||
|
|
||||||
|
+ // Lophine start - Global Entities Counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||||
|
+ uniqueId = fun.bm.lophine.utils.EntitiesCounterUtil.generateUniqueId();
|
||||||
|
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(world, spawnChunkTracker, uniqueId);
|
||||||
|
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(world, loadedEntities, uniqueId);
|
||||||
|
+ underGlobalEntitiesCounter = true;
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - Global Entities Counter
|
||||||
|
+
|
||||||
|
// tasks may be drained before the region ticks, so we must set up the tick data early just in case
|
||||||
|
this.updateTickData();
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
index 05bad0366bd36b8134290a0cceb4d4dfcbbd0544..604681c8fda696dcc824b1b36b53c0d8434ec5c2 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
@@ -516,6 +516,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
this.chunkMap.tick(hasTimeLeft);
|
||||||
|
profilerFiller.pop();
|
||||||
|
this.clearCache();
|
||||||
|
+ // Lophine start - Global Entities Counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||||
|
+ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData();
|
||||||
|
+ if (regionizedWorldData != null) {
|
||||||
|
+ if (regionizedWorldData.underGlobalEntitiesCounter) {
|
||||||
|
+ if (regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||||
|
+ fun.bm.lophine.utils.EntitiesCounterUtil.onWorldDataUnload(level, regionizedWorldData.uniqueId);
|
||||||
|
+ regionizedWorldData.underGlobalEntitiesCounter = false;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (!regionizedWorldData.getLocalPlayers().isEmpty()) {
|
||||||
|
+ fun.bm.lophine.utils.EntitiesCounterUtil.reportAreaMap(level, regionizedWorldData.spawnChunkTracker, regionizedWorldData.uniqueId);
|
||||||
|
+ fun.bm.lophine.utils.EntitiesCounterUtil.addDataToLoaded(level, (ca.spottedleaf.moonrise.common.list.ReferenceList<Entity>) regionizedWorldData.getLoadedEntities(), regionizedWorldData.uniqueId);
|
||||||
|
+ regionizedWorldData.underGlobalEntitiesCounter = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - Global Entities Counter
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickChunks() {
|
||||||
|
@@ -580,7 +599,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
}
|
||||||
|
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||||
|
} else {
|
||||||
|
+ // Lophine start - Global Entities Counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||||
|
+ spawnState = fun.bm.lophine.utils.EntitiesCounterUtil.runRemainingTasks(level, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||||
|
+ } else {
|
||||||
|
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - Global Entities Counter
|
||||||
|
}
|
||||||
|
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); } // Folia - profiler
|
||||||
|
// Paper end - Optional per player mob spawns
|
||||||
|
@@ -589,7 +614,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threading
|
||||||
|
int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||||
|
List<MobCategory> filteredSpawningCategories;
|
||||||
|
- if (_boolean && (this.spawnEnemies || this.spawnFriendlies)) {
|
||||||
|
+ if (spawnState != null && _boolean && (this.spawnEnemies || this.spawnFriendlies)) { // Lophine - Global Entities Counter
|
||||||
|
// Paper start - PlayerNaturallySpawnCreaturesEvent
|
||||||
|
for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading
|
||||||
|
int chunkRange = Math.min(level.spigotConfig.mobSpawnRange, entityPlayer.getBukkitEntity().getViewDistance());
|
||||||
|
@@ -646,7 +671,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
this.level.tickThunder(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!spawnCategories.isEmpty()) {
|
||||||
|
+ if (spawnState != null && !spawnCategories.isEmpty()) { // Lophine - Global Entities Counter
|
||||||
|
if (this.level.getWorldBorder().isWithinBounds(pos)) { // Paper - rewrite chunk system
|
||||||
|
NaturalSpawner.spawnForChunk(this.level, chunk, spawnState, spawnCategories);
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
index c0ba36849da0983117901f0cd04b2c785df0010b..0b0d9322632ef1a751add633bdcb87ec84f82704 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerLevel.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||||
|
@@ -729,6 +729,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(BooleanSupplier hasTimeLeft, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking
|
||||||
|
+ // Lophine start - Global Entities Counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.experiment.GlobalEntitiesCounter.enabled) {
|
||||||
|
+ if (fun.bm.lophine.utils.EntitiesCounterUtil.canRunNewTask(this)) fun.bm.lophine.utils.EntitiesCounterUtil.tick(this);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - Global Entities Counter
|
||||||
|
final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking
|
||||||
|
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
|
||||||
|
ProfilerFiller profilerFiller = Profiler.get();
|
||||||
|
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||||
|
index 81f4707cf1a7cbdfcfc519cfbe1052cde77aa755..5c53e2d61ce8483d5d9e93e9f3112074c704a546 100644
|
||||||
|
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||||
|
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||||
|
@@ -113,7 +113,7 @@ public final class NaturalSpawner {
|
||||||
|
return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator);
|
||||||
|
}
|
||||||
|
|
||||||
|
- static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) {
|
||||||
|
+ public static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { // Lophine - protected -> public
|
||||||
|
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -584,7 +584,7 @@ public final class NaturalSpawner {
|
||||||
|
private EntityType<?> lastCheckedType;
|
||||||
|
private double lastCharge;
|
||||||
|
|
||||||
|
- SpawnState(
|
||||||
|
+ public SpawnState( // Lophine - protected -> public
|
||||||
|
int spawnableChunkCount,
|
||||||
|
Object2IntOpenHashMap<MobCategory> mobCategoryCounts,
|
||||||
|
PotentialCalculator spawnPotential,
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Wed, 17 Dec 2025 00:20:57 +0800
|
||||||
|
Subject: [PATCH] Add null check in RegionizedWorldData >> conections
|
||||||
|
|
||||||
|
some of our function patches will crash because of get null in conn.getPlayer(), then when we process player.chunkPosition() will get NPE, so we need to fix it.
|
||||||
|
|
||||||
|
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
index 7cc41630a39c1e29840d70eee78473d06b7c11cd..d0ab09a77953c1ccd309637ba80c47a37114f082 100644
|
||||||
|
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||||
|
@@ -230,14 +230,17 @@ public final class RegionizedWorldData {
|
||||||
|
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift)).itemEntityMovementTrackerMap.put(key, tracker);
|
||||||
|
}
|
||||||
|
// Luminol end
|
||||||
|
+ Set<Connection> cons = new java.util.HashSet<>(from.connections.size()); // Lophine - save all connections we have processed in connection process
|
||||||
|
// connections
|
||||||
|
for (final Connection conn : from.connections) {
|
||||||
|
final ServerPlayer player = conn.getPlayer();
|
||||||
|
+ if (player == null) continue; // Lophine - skip null player connections
|
||||||
|
final ChunkPos pos = player.chunkPosition();
|
||||||
|
// Note: It is impossible for an entity in the world to _not_ be in an entity chunk, which means
|
||||||
|
// the chunk holder must _exist_, and so the region section exists.
|
||||||
|
regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
|
||||||
|
.connections.add(conn);
|
||||||
|
+ cons.add(conn); // Lophine - save all connections we have processed in connection process
|
||||||
|
}
|
||||||
|
// entities
|
||||||
|
for (final ServerPlayer player : from.localPlayers) {
|
||||||
|
@@ -247,6 +250,13 @@ public final class RegionizedWorldData {
|
||||||
|
final RegionizedWorldData into = regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift));
|
||||||
|
into.localPlayers.add(player);
|
||||||
|
into.nearbyPlayers.addPlayer(player);
|
||||||
|
+ // Lophine start - we need to process the connection if player's connection is not processed, if connection.player is null, next tick will clean up it
|
||||||
|
+ final Connection conn = player.connection.connection;
|
||||||
|
+ if (!cons.contains(conn)) {
|
||||||
|
+ regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift))
|
||||||
|
+ .connections.add(conn);
|
||||||
|
+ }
|
||||||
|
+ // Lophine end
|
||||||
|
}
|
||||||
|
for (final Entity entity : from.allEntities) {
|
||||||
|
final ChunkPos pos = entity.chunkPosition();
|
||||||
|
@@ -577,6 +587,7 @@ public final class RegionizedWorldData {
|
||||||
|
private static void cleanUpConnection(final Connection conn) {
|
||||||
|
// note: ALL connections HERE have a player
|
||||||
|
final ServerPlayer player = conn.getPlayer();
|
||||||
|
+ if (player == null) return; // Lophine - skip null player connections
|
||||||
|
// now that the connection is removed, we can allow this region to die
|
||||||
|
player.level().moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(
|
||||||
|
ServerGamePacketListenerImpl.DISCONNECT_TICKET, player.connection.disconnectPos,
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Tue, 13 Jan 2026 21:04:59 +0800
|
||||||
|
Subject: [PATCH] Add removed check before all checks start in addEffect
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
index 205e2648569b7c18f488aa4d3d9ec944bb1babf4..c6ee14f14e051b30012e608b84a055ff2468850d 100644
|
||||||
|
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||||
|
@@ -1174,6 +1174,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||||
|
public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
|
||||||
|
// Paper end - Don't fire sync event during generation
|
||||||
|
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
|
||||||
|
+ if (this.isRemoved()) return false; // Lophine - shouldn't be possible to add effects to removed entity
|
||||||
|
if (!this.hasNullCallback()) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add effects to entities asynchronously"); // Folia - region threading
|
||||||
|
if (this.isTickingEffects) {
|
||||||
|
this.effectsToProcess.add(new ProcessableEffect(effectInstance, cause));
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: mrhua269 <mrhua269@gmail.com>
|
||||||
|
Date: Sat, 3 Jan 2026 10:42:39 +0800
|
||||||
|
Subject: [PATCH] Luminol - 1.21.11: Sync dragon part when teleportation or
|
||||||
|
firstly created
|
||||||
|
|
||||||
|
A simple fix of https://github.com/PaperMC/Folia/issues/371
|
||||||
|
|
||||||
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
index e3a49083e75116622bd95fb17533730a6fb36752..545697d9c081a270ff47b332baee68372c0dd67d 100644
|
||||||
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
@@ -96,6 +96,7 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||||
|
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||||
|
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()), enderpearl.getId()); // Folia - region threading
|
||||||
|
}
|
||||||
|
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||||
|
entity.registerScheduler(); // Paper - optimise Folia entity scheduler
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
|
index f63252c580c313ccf89304866cfc6503f4b26052..f0ddf0bf462a316f82f4babac17af6860b6ba143 100644
|
||||||
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
|
@@ -4325,6 +4325,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
|
Entity copy = this.getType().create(destination, EntitySpawnReason.DIMENSION_TRAVEL);
|
||||||
|
copy.restoreFrom(this);
|
||||||
|
copy.transform(pos, yaw, pitch, velocity);
|
||||||
|
+ if (copy instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||||
|
if (toSameWorld) copy.notifyLithiumTrackerIfNeeded();// Luminol - region threading for sleeping block entity
|
||||||
|
// vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here
|
||||||
|
// for example, clearing of inventory after switching dimensions
|
||||||
|
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||||
|
index 84d215a498d9bf6f1232bf4af5a4a98d3ba9b131..2aa57b995d9fcfbd335655ef383314ce11d93707 100644
|
||||||
|
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||||
|
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||||
|
@@ -1003,4 +1003,12 @@ public class EnderDragon extends Mob implements Enemy {
|
||||||
|
return flag ? i : 0;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
+
|
||||||
|
+ // Luminol start - Sync dragon part when teleportation or firstly created
|
||||||
|
+ public void syncDragonPartsAfterTeleportTransform() {
|
||||||
|
+ for (EnderDragonPart part : this.subEntities) {
|
||||||
|
+ this.tickPart(part, 0.0, 0.0, 0.0); // offset -> 0.0
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Luminol end
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Sun, 16 Nov 2025 17:47:42 +0800
|
||||||
|
Subject: [PATCH] LeavesHooks
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||||
|
index e57c3ca79677b1dfe7cf3db36f0406de7ea5bd0a..86edd824ec42e550dd1419fd57d93a21fe2d648d 100644
|
||||||
|
--- a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||||
|
+++ b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
|
||||||
|
@@ -1 +1 @@
|
||||||
|
-ca.spottedleaf.moonrise.paper.PaperHooks
|
||||||
|
+org.leavesmc.leaves.region.LeavesHooks
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Sun, 16 Nov 2025 15:55:47 +0800
|
||||||
|
Subject: [PATCH] Leaves: Replay Mod API
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||||
|
index e1f456b31ffda9370b63e51f343847d6f9f62263..8a0f85241cc1530aacccc8b6ea24b9dec86fad66 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java
|
||||||
|
@@ -57,7 +57,7 @@ class PaperEventManager {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leaves start - skip bot
|
||||||
|
- if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot) {
|
||||||
|
+ if (event instanceof org.bukkit.event.player.PlayerEvent playerEvent && (playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.bot.Bot || playerEvent.getPlayer() instanceof org.leavesmc.leaves.entity.photographer.Photographer)) { // Leaves - and photographer
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Leaves end - skip bot
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
|
index 0a96721797b9bbc643f68677bbb1d10c3c89e815..7e2d870dc8b77c58270542f8916b9c9b88588809 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||||
|
@@ -317,6 +317,7 @@ public final class CraftServer implements Server {
|
||||||
|
public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
|
||||||
|
private final ServerConfiguration serverConfig = new PaperServerConfiguration();
|
||||||
|
private final org.leavesmc.leaves.entity.bot.CraftBotManager botManager; // Leaves
|
||||||
|
+ private final org.leavesmc.leaves.entity.photographer.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.photographer.CraftPhotographerManager(); // Leaves
|
||||||
|
|
||||||
|
// Paper start - Folia region threading API
|
||||||
|
private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
|
||||||
|
@@ -411,7 +412,7 @@ public final class CraftServer implements Server {
|
||||||
|
public CraftServer(DedicatedServer console, PlayerList playerList) {
|
||||||
|
this.console = console;
|
||||||
|
this.playerList = (DedicatedPlayerList) playerList;
|
||||||
|
- this.playerView = Collections.unmodifiableList(Lists.transform(playerList.players, new Function<ServerPlayer, CraftPlayer>() {
|
||||||
|
+ this.playerView = Collections.unmodifiableList(Lists.transform(playerList.realPlayers, new Function<ServerPlayer, CraftPlayer>() { // Leaves - replay api
|
||||||
|
@Override
|
||||||
|
public CraftPlayer apply(ServerPlayer player) {
|
||||||
|
return player.getBukkitEntity();
|
||||||
|
@@ -3333,4 +3334,11 @@ public final class CraftServer implements Server {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Folia end - region TPS API
|
||||||
|
+
|
||||||
|
+ // Leaves start - replay mod api
|
||||||
|
+ @Override
|
||||||
|
+ public org.leavesmc.leaves.entity.photographer.CraftPhotographerManager getPhotographerManager() {
|
||||||
|
+ return photographerManager;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - replay mod api
|
||||||
|
}
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||||
|
index 8eb5d014d9ed688ffebaffb4ce0bb40896961a04..634bd74449c6991ad72330d10f42ddbb7f59c164 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||||
|
@@ -127,6 +127,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { return new org.leavesmc.leaves.entity.bot.CraftBot(server, bot); }
|
||||||
|
+ if (entity instanceof org.leavesmc.leaves.replay.ServerPhotographer photographer) { return new org.leavesmc.leaves.entity.photographer.CraftPhotographer(server, photographer); }
|
||||||
|
|
||||||
|
// Special case complex part, since there is no extra entity type for them
|
||||||
|
if (entity instanceof EnderDragonPart complexPart) {
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
index 7883b7973570b5f275a03c6aac4d3b4392e7fa6e..18d066c605f8027d9b1170b64ef1428fb969631b 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||||
|
@@ -2214,7 +2214,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSee(Player player) {
|
||||||
|
- return this.canSee((org.bukkit.entity.Entity) player);
|
||||||
|
+ return !(player instanceof org.leavesmc.leaves.entity.photographer.Photographer) && this.canSee((org.bukkit.entity.Entity) player); // Leaves - skip photographer
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||||
|
index 7334422a6e0e7faec675cf038ccbca0e284f61b5..7fee749197b6c6a8890567a7a7819f45b290012b 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||||
|
@@ -338,7 +338,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||||
|
Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
- MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> {
|
||||||
|
+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().realPlayers.forEach(player -> { // Leaves - only real players
|
||||||
|
player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements());
|
||||||
|
player.getAdvancements().flushDirty(player, false);
|
||||||
|
});
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||||
|
index 25aae550dcdcef2df268d0dd99bdcc9bbd49fcf8..83af50de50a03e164d572f3c3466b6d0b42ed138 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
|
||||||
|
@@ -23,7 +23,7 @@ public class LazyPlayerSet extends LazyHashSet<Player> {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<Player> makePlayerSet(final MinecraftServer server) {
|
||||||
|
- List<ServerPlayer> players = server.getPlayerList().players;
|
||||||
|
+ List<ServerPlayer> players = server.getPlayerList().realPlayers; // Leaves - only real players
|
||||||
|
Set<Player> reference = new HashSet<>(players.size());
|
||||||
|
for (ServerPlayer player : players) {
|
||||||
|
reference.add(player.getBukkitEntity());
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Sat, 22 Nov 2025 01:43:26 +0800
|
||||||
|
Subject: [PATCH] add cancel task by task id in FoliaGlobalRegionScheduler
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||||
|
index d306f911757a4d556c82c0070d4837db87afc497..7c9d3e4c399b2ea246a76b4550ba12e45e75078e 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
|
||||||
|
@@ -17,6 +17,8 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
private long tickCount = 0L;
|
||||||
|
private final Object stateLock = new Object();
|
||||||
|
private final Long2ObjectOpenHashMap<List<GlobalScheduledTask>> tasksByDeadline = new Long2ObjectOpenHashMap<>();
|
||||||
|
+ private int lastTaskId = 1; // Lophine - add task id
|
||||||
|
+ private final Object stateLockForTaskId = new Object(); // Lophine - add task id
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
final List<GlobalScheduledTask> run;
|
||||||
|
@@ -65,7 +67,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task);
|
||||||
|
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task, this.getNextTaskId()); // Lophine - add task id
|
||||||
|
|
||||||
|
this.scheduleInternal(ret, delayTicks);
|
||||||
|
|
||||||
|
@@ -92,7 +94,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task);
|
||||||
|
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task, this.getNextTaskId()); // Lophine - add task id
|
||||||
|
|
||||||
|
this.scheduleInternal(ret, initialDelayTicks);
|
||||||
|
|
||||||
|
@@ -134,7 +136,33 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- private final class GlobalScheduledTask implements ScheduledTask, Runnable {
|
||||||
|
+ // Lophine start - add cancel task by task id
|
||||||
|
+ public void cancelTask(final int taskId) {
|
||||||
|
+ synchronized (this.stateLock) {
|
||||||
|
+ for (final List<GlobalScheduledTask> tasks : this.tasksByDeadline.values()) {
|
||||||
|
+ for (final GlobalScheduledTask task : tasks) {
|
||||||
|
+ if (task.getTaskId() == taskId) {
|
||||||
|
+ task.cancel();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private int getNextTaskId() {
|
||||||
|
+ synchronized (this.stateLockForTaskId) {
|
||||||
|
+ if (this.lastTaskId == Integer.MAX_VALUE) {
|
||||||
|
+ this.lastTaskId = 1;
|
||||||
|
+ } else {
|
||||||
|
+ ++this.lastTaskId;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return this.lastTaskId;
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - add cancel task by task id
|
||||||
|
+
|
||||||
|
+ public final class GlobalScheduledTask implements ScheduledTask, Runnable { // Lophine - private -> public
|
||||||
|
|
||||||
|
private static final int STATE_IDLE = 0;
|
||||||
|
private static final int STATE_EXECUTING = 1;
|
||||||
|
@@ -146,13 +174,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
private final long repeatDelay; // in ticks
|
||||||
|
private Consumer<ScheduledTask> run;
|
||||||
|
private volatile int state;
|
||||||
|
+ private int taskId; // Lophine - add task id
|
||||||
|
|
||||||
|
private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
|
||||||
|
|
||||||
|
- private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run) {
|
||||||
|
+ private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run, int taskId) { // Lophine - add task id
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.repeatDelay = repeatDelay;
|
||||||
|
this.run = run;
|
||||||
|
+ this.taskId = taskId; // Lophine - add task id
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int getStateVolatile() {
|
||||||
|
@@ -263,5 +293,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // Lophine start - add task id
|
||||||
|
+ public int getTaskId() {
|
||||||
|
+ return taskId;
|
||||||
|
+ }
|
||||||
|
+ // Lophine end - add task id
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package fun.bm.lophine;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class LophineLogger {
|
||||||
|
public static final Logger LOGGER = LogUtils.getClassLogger(); // only provided for some Logger can not be initialized
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package fun.bm.lophine.carpet;
|
||||||
|
|
||||||
|
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public final class CarpetCalculatorCompatHelper {
|
||||||
|
|
||||||
|
public static boolean handleChat(ServerPlayer player, String rawMessage) {
|
||||||
|
if (!GeneralCompatConfig.simpleInGameCalculator || !rawMessage.startsWith("=")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String expression = rawMessage.substring(1).trim();
|
||||||
|
if (expression.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component response;
|
||||||
|
try {
|
||||||
|
double result = new ExpressionBuilder(expression).build().evaluate();
|
||||||
|
response = Component.literal(expression + " = " + formatNumber(result)).withStyle(ChatFormatting.YELLOW);
|
||||||
|
} catch (RuntimeException exception) {
|
||||||
|
response = Component.literal("Calculator error: " + exception.getMessage()).withStyle(ChatFormatting.RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component scheduledResponse = response;
|
||||||
|
player.getBukkitEntity().taskScheduler.schedule((ServerPlayer scheduledPlayer) -> scheduledPlayer.sendSystemMessage(scheduledResponse), null, 1L);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatNumber(double value) {
|
||||||
|
if (Double.isFinite(value) && Math.rint(value) == value && value >= Long.MIN_VALUE && value <= Long.MAX_VALUE) {
|
||||||
|
return Long.toString((long) value);
|
||||||
|
}
|
||||||
|
return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package fun.bm.lophine.carpet;
|
||||||
|
|
||||||
|
import fun.bm.lophine.carpet.config.modules.CoreConfig;
|
||||||
|
import fun.bm.lophine.carpet.config.modules.CounterCompatConfig;
|
||||||
|
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
|
||||||
|
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||||
|
import fun.bm.lophine.config.modules.experiment.CommandConfig;
|
||||||
|
import fun.bm.lophine.config.modules.experiment.RedStoneConfig;
|
||||||
|
import fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig;
|
||||||
|
import fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig;
|
||||||
|
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
|
||||||
|
import fun.bm.lophine.config.modules.function.LanguageConfig;
|
||||||
|
import fun.bm.lophine.config.modules.function.WoolHopperCounterConfig;
|
||||||
|
import fun.bm.lophine.protocol.CarpetLoggerProtocol;
|
||||||
|
import me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig;
|
||||||
|
import org.leavesmc.leaves.bot.ServerBot;
|
||||||
|
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// WARNING: THIS FILE NEED TO FULLY REWRITTEN
|
||||||
|
public final class CarpetCompatSync {
|
||||||
|
private static boolean init = false;
|
||||||
|
|
||||||
|
public static void apply() {
|
||||||
|
if (init) return;
|
||||||
|
if (CoreConfig.enabled) {
|
||||||
|
applyGeneralRules();
|
||||||
|
applyFakePlayerRules();
|
||||||
|
applyCounterRules();
|
||||||
|
}
|
||||||
|
CarpetLoggerProtocol.refreshConfiguredDefaults(!init);
|
||||||
|
registerProtocolRules();
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyGeneralRules() {
|
||||||
|
LanguageConfig.lang = GeneralCompatConfig.language;
|
||||||
|
UpdateSuppressionCrashFixConfig.enabled = GeneralCompatConfig.amsUpdateSuppressionCrashFix || GeneralCompatConfig.yeetUpdateSuppressionCrash;
|
||||||
|
RedStoneConfig.redstoneIgnoreUpwardsUpdate = GeneralCompatConfig.dustTrapdoorReintroduced;
|
||||||
|
RedStoneConfig.cce = GeneralCompatConfig.shulkerBoxCCEReintroduced;
|
||||||
|
RedStoneConfig.instantBlockUpdater = GeneralCompatConfig.instantBlockUpdaterReintroduced;
|
||||||
|
CommandConfig.tick = GeneralCompatConfig.commandTick;
|
||||||
|
CreativeFlyNoClipConfig.enabled = GeneralCompatConfig.creativeNoClip;
|
||||||
|
OptimizedDragonRespawnConfig.optimizedRespawn = GeneralCompatConfig.optimizedDragonRespawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyFakePlayerRules() {
|
||||||
|
FakeplayerConfig.enable = FakePlayerCompatConfig.commandBot || FakePlayerCompatConfig.commandPlayer;
|
||||||
|
FakeplayerConfig.canResident = FakePlayerCompatConfig.fakePlayerResident;
|
||||||
|
FakeplayerConfig.canOpenInventory = FakePlayerCompatConfig.openFakePlayerInventory;
|
||||||
|
FakeplayerConfig.tickType = FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer
|
||||||
|
? ServerBot.TickType.NETWORK
|
||||||
|
: ServerBot.TickType.ENTITY_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyCounterRules() {
|
||||||
|
WoolHopperCounterConfig.enabled = CounterCompatConfig.hopperCounters;
|
||||||
|
WoolHopperCounterConfig.unlimitedSpeed = CounterCompatConfig.hopperCountersUnlimitedSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> sanitizeDefaultLoggers(List<String> configuredLoggers) {
|
||||||
|
return configuredLoggers == null ? List.of() : List.copyOf(configuredLoggers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerProtocolRules() {
|
||||||
|
CarpetServerProtocol.CarpetRules.clear();
|
||||||
|
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "language", GeneralCompatConfig.language));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "amsUpdateSuppressionCrashFix", GeneralCompatConfig.amsUpdateSuppressionCrashFix));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "yeetUpdateSuppressionCrash", GeneralCompatConfig.yeetUpdateSuppressionCrash));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "dustTrapdoorReintroduced", GeneralCompatConfig.dustTrapdoorReintroduced));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "shulkerBoxCCEReintroduced", GeneralCompatConfig.shulkerBoxCCEReintroduced));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "instantBlockUpdaterReintroduced", GeneralCompatConfig.instantBlockUpdaterReintroduced));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandTick", GeneralCompatConfig.commandTick));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "creativeNoClip", GeneralCompatConfig.creativeNoClip));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedDragonRespawn", GeneralCompatConfig.optimizedDragonRespawn));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "antiSpamDisabled", GeneralCompatConfig.antiSpamDisabled));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "blockPlacementIgnoreEntity", GeneralCompatConfig.blockPlacementIgnoreEntity));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "creativeOpenContainerForcibly", GeneralCompatConfig.creativeOpenContainerForcibly));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "creativeOneHitKill", GeneralCompatConfig.creativeOneHitKill));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "observerNoDetection", GeneralCompatConfig.observerNoDetection));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "bambooModelNoOffset", GeneralCompatConfig.bambooModelNoOffset));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "creativeNoItemCooldown", GeneralCompatConfig.creativeNoItemCooldown));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "ctrlQCraftingFix", GeneralCompatConfig.ctrlQCraftingFix));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "carpetAlwaysSetDefault", GeneralCompatConfig.carpetAlwaysSetDefault));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "placementRotationFix", GeneralCompatConfig.placementRotationFix));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "tntDoNotUpdate", GeneralCompatConfig.tntDoNotUpdate));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "totallyNoBlockUpdate", GeneralCompatConfig.totallyNoBlockUpdate));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tiscmNetworkProtocol", GeneralCompatConfig.tiscmNetworkProtocol));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetorgaddition", "hopperNoItemCost", GeneralCompatConfig.hopperNoItemCost));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "explosionNoBlockDamage", GeneralCompatConfig.explosionNoBlockDamage));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedTNTHighPriority", GeneralCompatConfig.optimizedTNTHighPriority));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "tntPrimerMomentumRemoved", GeneralCompatConfig.tntPrimerMomentumRemoved));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntIgnoreRedstoneSignal", GeneralCompatConfig.tntIgnoreRedstoneSignal));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntDupingFix", GeneralCompatConfig.tntDupingFix));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "interactionUpdates", GeneralCompatConfig.interactionUpdates));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "xpNoCooldown", GeneralCompatConfig.xpNoCooldown));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "powerfulExpMending", GeneralCompatConfig.powerfulExpMending));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "clientSettingsLostOnRespawnFix", GeneralCompatConfig.clientSettingsLostOnRespawnFix));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "sensibleEnderman", GeneralCompatConfig.sensibleEnderman));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "entityInstantDeathRemoval", GeneralCompatConfig.entityInstantDeathRemoval));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "farmlandTrampledDisabled", GeneralCompatConfig.farmlandTrampledDisabled));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "shulkerGolem", GeneralCompatConfig.shulkerGolem));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "preventEndSpikeRespawn", GeneralCompatConfig.preventEndSpikeRespawn));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "yeetOutOfOrderChatKick", GeneralCompatConfig.yeetOutOfOrderChatKick));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "betterCraftableBoneBlock", GeneralCompatConfig.betterCraftableBoneBlock));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "betterCraftableDispenser", GeneralCompatConfig.betterCraftableDispenser));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "viewDistance", GeneralCompatConfig.viewDistance));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tickCommandPermission", GeneralCompatConfig.normalizedTickCommandPermission()));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tickFreezeCommandToggleable", GeneralCompatConfig.tickFreezeCommandToggleable));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "syncServerMsptMetricsData", GeneralCompatConfig.syncServerMsptMetricsData));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetorgaddition", "simpleInGameCalculator", GeneralCompatConfig.simpleInGameCalculator));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "microTiming", GeneralCompatConfig.microTiming));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "fastRedstoneDust", GeneralCompatConfig.fastRedstoneDust));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "lagFreeSpawning", GeneralCompatConfig.lagFreeSpawning));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedFastEntityMovement", GeneralCompatConfig.optimizedFastEntityMovement));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "optimizedHardHitBoxEntityCollision", GeneralCompatConfig.optimizedHardHitBoxEntityCollision));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "tntFuseDuration", GeneralCompatConfig.normalizedTntFuseDuration()));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "defaultLoggers", CarpetLoggerProtocol.serializeConfiguredDefaults(sanitizeDefaultLoggers(GeneralCompatConfig.defaultLoggers))));
|
||||||
|
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "commandBot", FakePlayerCompatConfig.commandBot));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "commandPlayer", FakePlayerCompatConfig.commandPlayer));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerResident", FakePlayerCompatConfig.fakePlayerResident));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "openFakePlayerInventory", FakePlayerCompatConfig.openFakePlayerInventory));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "fakePlayerTicksLikeRealPlayer", FakePlayerCompatConfig.fakePlayerTicksLikeRealPlayer));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerDefaultSurvivalMode", FakePlayerCompatConfig.fakePlayerDefaultSurvivalMode));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerInteractLikeClient", FakePlayerCompatConfig.fakePlayerInteractLikeClient));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoReplaceTool", FakePlayerCompatConfig.fakePlayerAutoReplaceTool));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoReplenishment", FakePlayerCompatConfig.fakePlayerAutoReplenishment));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpetamsaddition", "fakePlayerAutoReplenishmentFormShulkerBox", FakePlayerCompatConfig.fakePlayerAutoReplenishmentFormShulkerBox));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerAutoFish", FakePlayerCompatConfig.fakePlayerAutoFish));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("lophine", "fakePlayerReloadAction", FakePlayerCompatConfig.fakePlayerReloadAction));
|
||||||
|
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "hopperCounters", CounterCompatConfig.hopperCounters));
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpettisaddition", "hopperCountersUnlimitedSpeed", CounterCompatConfig.hopperCountersUnlimitedSpeed));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package fun.bm.lophine.carpet;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public final class InteractionUpdateCompatHelper {
|
||||||
|
private static final ThreadLocal<Integer> SUPPRESSED_DEPTH = ThreadLocal.withInitial(() -> 0);
|
||||||
|
|
||||||
|
public static boolean shouldSkipUpdates() {
|
||||||
|
return SUPPRESSED_DEPTH.get() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runWithSuppressedUpdates(Runnable action) {
|
||||||
|
push();
|
||||||
|
try {
|
||||||
|
action.run();
|
||||||
|
} finally {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T supplyWithSuppressedUpdates(Supplier<T> action) {
|
||||||
|
push();
|
||||||
|
try {
|
||||||
|
return action.get();
|
||||||
|
} finally {
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void push() {
|
||||||
|
SUPPRESSED_DEPTH.set(SUPPRESSED_DEPTH.get() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void pop() {
|
||||||
|
int depth = SUPPRESSED_DEPTH.get();
|
||||||
|
if (depth <= 1) {
|
||||||
|
SUPPRESSED_DEPTH.remove();
|
||||||
|
} else {
|
||||||
|
SUPPRESSED_DEPTH.set(depth - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package fun.bm.lophine.carpet;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import io.papermc.paper.threadedregions.RegionizedWorldData;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.tags.BlockTags;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.EntitySpawnReason;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import net.minecraft.world.entity.Mob;
|
||||||
|
import net.minecraft.world.entity.MobCategory;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.FenceGateBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
public final class LagFreeSpawningCompatHelper {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
private static final Map<RegionizedWorldData, Map<EntityType<?>, Mob>> PRECOOKED_MOBS = new WeakHashMap<>();
|
||||||
|
|
||||||
|
public static boolean hasNoCollision(ServerLevel world, AABB bb) {
|
||||||
|
if (!TickThread.isTickThreadFor(world, bb)) return world.noCollision(bb);
|
||||||
|
int minX = Mth.floor(bb.minX);
|
||||||
|
int minY = Mth.floor(bb.minY);
|
||||||
|
int minZ = Mth.floor(bb.minZ);
|
||||||
|
int maxY = Mth.ceil(bb.maxY) - 1;
|
||||||
|
BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
|
if (bb.getXsize() <= 1.0 && bb.getZsize() <= 1.0) {
|
||||||
|
for (int y = minY; y <= maxY; y++) {
|
||||||
|
blockPos.set(minX, y, minZ);
|
||||||
|
VoxelShape shape = world.getBlockState(blockPos).getCollisionShape(world, blockPos);
|
||||||
|
if (shape != Shapes.empty()) {
|
||||||
|
return shape != Shapes.block() && world.noCollision(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxX = Mth.ceil(bb.maxX) - 1;
|
||||||
|
int maxZ = Mth.ceil(bb.maxZ) - 1;
|
||||||
|
|
||||||
|
for (int y = minY; y <= maxY; y++) {
|
||||||
|
for (int x = minX; x <= maxX; x++) {
|
||||||
|
for (int z = minZ; z <= maxZ; z++) {
|
||||||
|
blockPos.set(x, y, z);
|
||||||
|
VoxelShape shape = world.getBlockState(blockPos).getCollisionShape(world, blockPos);
|
||||||
|
if (shape != Shapes.empty()) {
|
||||||
|
return shape != Shapes.block() && world.noCollision(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int minBelow = minY - 1;
|
||||||
|
for (int x = minX; x <= maxX; x++) {
|
||||||
|
for (int z = minZ; z <= maxZ; z++) {
|
||||||
|
blockPos.set(x, minBelow, z);
|
||||||
|
BlockState state = world.getBlockState(blockPos);
|
||||||
|
Block block = state.getBlock();
|
||||||
|
if (state.is(BlockTags.FENCES)
|
||||||
|
|| state.is(BlockTags.WALLS)
|
||||||
|
|| block instanceof FenceGateBlock && !state.getValue(FenceGateBlock.OPEN)) {
|
||||||
|
if (x == minX || x == maxX || z == minZ || z == maxZ) {
|
||||||
|
return world.noCollision(bb);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double limitDistanceSq(MobCategory category, double distanceSq) {
|
||||||
|
return distanceSq > 16384.0 && category != MobCategory.CREATURE ? 0.0 : distanceSq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable Mob getOrCreateMob(ServerLevel level, EntityType<?> entityType) {
|
||||||
|
RegionizedWorldData data = level.getCurrentWorldData();
|
||||||
|
if (data == null) return createMob(level, entityType);
|
||||||
|
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.computeIfAbsent(level.getCurrentWorldData(), key -> new HashMap<>());
|
||||||
|
Mob mob = cache.get(entityType);
|
||||||
|
if (mob != null && !mob.isRemoved()) {
|
||||||
|
if (!TickThread.isTickThreadFor(mob)) return createMob(level, entityType);
|
||||||
|
return mob;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createMob(level, entityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable Mob createMob(ServerLevel level, EntityType<?> entityType) {
|
||||||
|
try {
|
||||||
|
if (entityType.create(level, EntitySpawnReason.NATURAL) instanceof Mob created) {
|
||||||
|
PRECOOKED_MOBS.get(level.getCurrentWorldData()).put(entityType, created);
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
LOGGER.warn("Can't precook non-mob entity type: {}", entityType);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
LOGGER.warn("Failed to precook mob {}", entityType, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markSpawned(ServerLevel level, EntityType<?> entityType) {
|
||||||
|
Map<EntityType<?>, Mob> cache = PRECOOKED_MOBS.get(level.getCurrentWorldData());
|
||||||
|
if (cache != null) {
|
||||||
|
cache.remove(entityType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package fun.bm.lophine.carpet.config.modules;
|
||||||
|
|
||||||
|
import fun.bm.lophine.carpet.CarpetCompatSync;
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(
|
||||||
|
category = EnumConfigCategory.ROOT,
|
||||||
|
name = "core",
|
||||||
|
directory = {"carpet"}
|
||||||
|
)
|
||||||
|
public class CoreConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
|
Enable carpet features.
|
||||||
|
If you want to use some function from Carpet modifier,
|
||||||
|
you need to enable it.
|
||||||
|
(some function is not managed by this option)
|
||||||
|
|
||||||
|
ONLY GENERAL DIRECTORY WAS CONTROLLED BY THIS OPTION.
|
||||||
|
WARNING: IF YOU ENABLED IT, ORIGINAL CONFIG IN LOPHINE CONFIG WILL BE OVERWRITTEN.""")
|
||||||
|
public static boolean enabled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeFinalLoad() {
|
||||||
|
CarpetCompatSync.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package fun.bm.lophine.carpet.config.modules;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(
|
||||||
|
category = EnumConfigCategory.ROOT,
|
||||||
|
name = "hopper_counter",
|
||||||
|
directory = {"carpet"},
|
||||||
|
comments = """
|
||||||
|
Hopper counter compatibility mapped onto Lophine's wool hopper counter implementation."""
|
||||||
|
)
|
||||||
|
public class CounterCompatConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "hopperCounters", comments = """
|
||||||
|
Enable the existing wool hopper counter implementation.""")
|
||||||
|
public static boolean hopperCounters = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
|
||||||
|
Remove the hopper transfer speed limit for counters.
|
||||||
|
Only effective when hopperCounters is enabled.""")
|
||||||
|
public static boolean hopperCountersUnlimitedSpeed = false;
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package fun.bm.lophine.carpet.config.modules;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(
|
||||||
|
category = EnumConfigCategory.ROOT,
|
||||||
|
name = "fakeplayer",
|
||||||
|
directory = {"carpet"},
|
||||||
|
comments = """
|
||||||
|
Carpet fakeplayer compatibility mapped onto Lophine fakeplayers.
|
||||||
|
commandPlayer is currently backed by Lophine's /bot command surface."""
|
||||||
|
)
|
||||||
|
public class FakePlayerCompatConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "commandBot", comments = """
|
||||||
|
Enable Lophine's /bot command.""")
|
||||||
|
public static boolean commandBot = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "commandPlayer", comments = """
|
||||||
|
Map Carpet's commandPlayer rule to the same fakeplayer command surface used by /bot.""")
|
||||||
|
public static boolean commandPlayer = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerResident", comments = """
|
||||||
|
Keep fakeplayers resident across unload and restart.""")
|
||||||
|
public static boolean fakePlayerResident = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "openFakePlayerInventory", comments = """
|
||||||
|
Allow opening fakeplayer inventories.""")
|
||||||
|
public static boolean openFakePlayerInventory = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerTicksLikeRealPlayer", comments = """
|
||||||
|
Tick fakeplayers in the network phase to better match real player timing.""")
|
||||||
|
public static boolean fakePlayerTicksLikeRealPlayer = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerDefaultSurvivalMode", comments = """
|
||||||
|
Force newly created fakeplayers to start in survival instead of the server default gamemode.""")
|
||||||
|
public static boolean fakePlayerDefaultSurvivalMode = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerInteractLikeClient", comments = """
|
||||||
|
Make fakeplayer entity interaction follow client-side fallback behavior more closely.""")
|
||||||
|
public static boolean fakePlayerInteractLikeClient = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerAutoReplaceTool", comments = """
|
||||||
|
Toggle automatic tool replacement for fakeplayers.""")
|
||||||
|
public static boolean fakePlayerAutoReplaceTool = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerAutoReplenishment", comments = """
|
||||||
|
Toggle automatic stack replenishment for fakeplayers.""")
|
||||||
|
public static boolean fakePlayerAutoReplenishment = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerAutoReplenishmentFormShulkerBox", comments = """
|
||||||
|
Let fakeplayer replenishment pull matching items out of shulker boxes in the inventory.""")
|
||||||
|
public static boolean fakePlayerAutoReplenishmentFormShulkerBox = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerAutoFish", comments = """
|
||||||
|
Let fakeplayers holding a fishing rod automatically cast and reel it in.""")
|
||||||
|
public static boolean fakePlayerAutoFish = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fakePlayerReloadAction", comments = """
|
||||||
|
Persist queued fakeplayer actions across save and reload.""")
|
||||||
|
public static boolean fakePlayerReloadAction = false;
|
||||||
|
}
|
||||||
+239
@@ -0,0 +1,239 @@
|
|||||||
|
package fun.bm.lophine.carpet.config.modules;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ConfigClassInfo(
|
||||||
|
category = EnumConfigCategory.ROOT,
|
||||||
|
name = "general",
|
||||||
|
directory = {"carpet"},
|
||||||
|
comments = """
|
||||||
|
Carpet/AMS/TIS/Org compatibility rules backed by existing Lophine features.
|
||||||
|
Only rules that already have a working server-side implementation are exposed here."""
|
||||||
|
)
|
||||||
|
public class GeneralCompatConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "language", comments = """
|
||||||
|
Carpet language value forwarded to lophine.function.language.lang.""")
|
||||||
|
public static String language = "en_us";
|
||||||
|
|
||||||
|
@ConfigInfo(name = "amsUpdateSuppressionCrashFix", comments = """
|
||||||
|
Map AMS update suppression crash protection to Lophine's existing crash fix.""")
|
||||||
|
public static boolean amsUpdateSuppressionCrashFix = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "yeetUpdateSuppressionCrash", comments = """
|
||||||
|
Map TIS update suppression crash yeeting to the same Lophine crash fix.""")
|
||||||
|
public static boolean yeetUpdateSuppressionCrash = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "dustTrapdoorReintroduced", comments = """
|
||||||
|
Map dust-on-open-trapdoor behavior to Lophine's redstone-ignore-upwards-update option.""")
|
||||||
|
public static boolean dustTrapdoorReintroduced = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "shulkerBoxCCEReintroduced", comments = """
|
||||||
|
Map shulker-box CCE update suppression to Lophine's cce-update-suppression option.""")
|
||||||
|
public static boolean shulkerBoxCCEReintroduced = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "instantBlockUpdaterReintroduced", comments = """
|
||||||
|
Enable the existing instant block updater patch already carried by Lophine.""")
|
||||||
|
public static boolean instantBlockUpdaterReintroduced = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "commandTick", comments = """
|
||||||
|
Enable the tick command support already patched into Lophine.""")
|
||||||
|
public static boolean commandTick = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "creativeNoClip", comments = """
|
||||||
|
Enable the existing creative fly no clip implementation.""")
|
||||||
|
public static boolean creativeNoClip = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "optimizedDragonRespawn", comments = """
|
||||||
|
Enable the existing optimized dragon respawn implementation from Luminol.""")
|
||||||
|
public static boolean optimizedDragonRespawn = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "antiSpamDisabled", comments = """
|
||||||
|
Disable the server-side chat and creative-drop spam throttles used by vanilla/Spigot.""")
|
||||||
|
public static boolean antiSpamDisabled = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "blockPlacementIgnoreEntity", comments = """
|
||||||
|
Allow creative players to place blocks without entity collision checks.""")
|
||||||
|
public static boolean blockPlacementIgnoreEntity = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "creativeOpenContainerForcibly", comments = """
|
||||||
|
Allow creative players to forcibly open blocked chests, ender chests and shulker boxes.""")
|
||||||
|
public static boolean creativeOpenContainerForcibly = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "creativeOneHitKill", comments = """
|
||||||
|
Allow creative players to instantly kill attackable non-creative, non-spectator entities.
|
||||||
|
Sneaking expands the effect into a small area attack.""")
|
||||||
|
public static boolean creativeOneHitKill = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "observerNoDetection", comments = """
|
||||||
|
Disable observer detection pulses entirely.""")
|
||||||
|
public static boolean observerNoDetection = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "bambooModelNoOffset", comments = """
|
||||||
|
Remove the random horizontal model offset from bamboo and bamboo saplings.""")
|
||||||
|
public static boolean bambooModelNoOffset = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "creativeNoItemCooldown", comments = """
|
||||||
|
Skip item cooldown application for creative players.""")
|
||||||
|
public static boolean creativeNoItemCooldown = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "ctrlQCraftingFix", comments = """
|
||||||
|
Compatibility flag for the upstream result-slot Ctrl+Q crafting fix already present in the current menu code.""")
|
||||||
|
public static boolean ctrlQCraftingFix = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "carpetAlwaysSetDefault", comments = """
|
||||||
|
Compatibility flag for Lophine's config loader, which already writes default values into the compat config during preload.""")
|
||||||
|
public static boolean carpetAlwaysSetDefault = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "placementRotationFix", comments = """
|
||||||
|
Use the player's main body rotation for placement direction checks instead of interpolated head yaw.""")
|
||||||
|
public static boolean placementRotationFix = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tntDoNotUpdate", comments = """
|
||||||
|
Prevent TNT from checking redstone power when first placed.""")
|
||||||
|
public static boolean tntDoNotUpdate = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "totallyNoBlockUpdate", comments = """
|
||||||
|
Suppress neighbor and shape updates globally for block changes.""")
|
||||||
|
public static boolean totallyNoBlockUpdate = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tiscmNetworkProtocol", comments = """
|
||||||
|
Enable the native Carpet TIS Addition network channel on `tiscm:network/v1`.""")
|
||||||
|
public static boolean tiscmNetworkProtocol = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "hopperNoItemCost", comments = """
|
||||||
|
Restore the transferred stack into a hopper when a wool block is placed on top of it.""")
|
||||||
|
public static boolean hopperNoItemCost = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "explosionNoBlockDamage", comments = """
|
||||||
|
Let explosions damage entities without breaking blocks.""")
|
||||||
|
public static boolean explosionNoBlockDamage = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "optimizedTNTHighPriority", comments = """
|
||||||
|
Compatibility flag for the already optimized server explosion path carried by the current runtime.""")
|
||||||
|
public static boolean optimizedTNTHighPriority = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tntPrimerMomentumRemoved", comments = """
|
||||||
|
Remove the random horizontal launch momentum from newly primed TNT.""")
|
||||||
|
public static boolean tntPrimerMomentumRemoved = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tntIgnoreRedstoneSignal", comments = """
|
||||||
|
Ignore redstone power when deciding whether TNT should auto-prime.""")
|
||||||
|
public static boolean tntIgnoreRedstoneSignal = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tntDupingFix", comments = """
|
||||||
|
Toggle the piston desync path used by vanilla TNT duplication setups.""")
|
||||||
|
public static boolean tntDupingFix = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "interactionUpdates", comments = """
|
||||||
|
Control whether player interaction block changes emit normal block updates.
|
||||||
|
Set to false to suppress neighbor and shape updates during block use and breaking.""")
|
||||||
|
public static boolean interactionUpdates = true;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "xpNoCooldown", comments = """
|
||||||
|
Allow players to absorb multiple experience orbs in the same tick without pickup delay.""")
|
||||||
|
public static boolean xpNoCooldown = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "powerfulExpMending", comments = """
|
||||||
|
Let picked-up experience repair all damaged mending items in the player's inventory, not only equipped gear.""")
|
||||||
|
public static boolean powerfulExpMending = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "clientSettingsLostOnRespawnFix", comments = """
|
||||||
|
Reapply the player's last known client settings after respawn.""")
|
||||||
|
public static boolean clientSettingsLostOnRespawnFix = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "sensibleEnderman", comments = """
|
||||||
|
Restrict enderman block pickup to pumpkins and melons only.""")
|
||||||
|
public static boolean sensibleEnderman = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "entityInstantDeathRemoval", comments = """
|
||||||
|
Remove the normal 20gt delay before dead living entities are discarded.""")
|
||||||
|
public static boolean entityInstantDeathRemoval = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "farmlandTrampledDisabled", comments = """
|
||||||
|
Prevent farmland from turning into dirt when entities land on it.""")
|
||||||
|
public static boolean farmlandTrampledDisabled = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "shulkerGolem", comments = """
|
||||||
|
Allow a carved pumpkin on top of a shulker box to summon a shulker.""")
|
||||||
|
public static boolean shulkerGolem = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "preventEndSpikeRespawn", comments = """
|
||||||
|
Skip obsidian spike regeneration during dragon respawn.""")
|
||||||
|
public static boolean preventEndSpikeRespawn = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "yeetOutOfOrderChatKick", comments = """
|
||||||
|
Ignore out-of-order secure chat chain checks instead of invalidating the chat session.""")
|
||||||
|
public static boolean yeetOutOfOrderChatKick = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "betterCraftableBoneBlock", comments = """
|
||||||
|
Add the AMS alternate bone block recipe that yields 3 bone blocks from 9 bones.""")
|
||||||
|
public static boolean betterCraftableBoneBlock = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "betterCraftableDispenser", comments = """
|
||||||
|
Add the AMS alternate dispenser recipes using a dropper.""")
|
||||||
|
public static boolean betterCraftableDispenser = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "viewDistance", comments = """
|
||||||
|
Override the dedicated server's startup view distance with the Carpet-compatible value.""")
|
||||||
|
public static int viewDistance = 12;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tickCommandPermission", comments = """
|
||||||
|
Override the `/tick` command permission level.
|
||||||
|
Accepts values in the range 0..4, where 2 matches old Carpet behavior and 3 keeps vanilla.""")
|
||||||
|
public static int tickCommandPermission = 3;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tickFreezeCommandToggleable", comments = """
|
||||||
|
Make `/tick freeze` toggle back to running when executed while the server is already frozen.""")
|
||||||
|
public static boolean tickFreezeCommandToggleable = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "syncServerMsptMetricsData", comments = """
|
||||||
|
Broadcast live MSPT samples through the native TISCM protocol channel.""")
|
||||||
|
public static boolean syncServerMsptMetricsData = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "simpleInGameCalculator", comments = """
|
||||||
|
Evaluate chat messages prefixed with `=` as a simple calculator expression and reply privately.""")
|
||||||
|
public static boolean simpleInGameCalculator = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "microTiming", comments = """
|
||||||
|
Compatibility flag for the built-in region profiler and timing instrumentation carried by Folia/Moonrise.""")
|
||||||
|
public static boolean microTiming = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "fastRedstoneDust", comments = """
|
||||||
|
Route redstone dust updates through the Alternate Current fast-update backend.""")
|
||||||
|
public static boolean fastRedstoneDust = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "lagFreeSpawning", comments = """
|
||||||
|
Use the lightweight collision and precooked-mob spawning path for natural spawning checks.""")
|
||||||
|
public static boolean lagFreeSpawning = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "optimizedFastEntityMovement", comments = """
|
||||||
|
Compatibility flag for the always-on Moonrise/Paper fast entity movement collision pipeline.""")
|
||||||
|
public static boolean optimizedFastEntityMovement = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "optimizedHardHitBoxEntityCollision", comments = """
|
||||||
|
Compatibility flag for the always-on Moonrise/Paper hard-hitbox entity collision optimizations.""")
|
||||||
|
public static boolean optimizedHardHitBoxEntityCollision = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "tntFuseDuration", comments = """
|
||||||
|
Override the default primed TNT fuse duration in ticks.
|
||||||
|
Accepts values in the range 0..32767.""")
|
||||||
|
public static int tntFuseDuration = 80;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "defaultLoggers", comments = """
|
||||||
|
Carpet-style default logger subscriptions for players.
|
||||||
|
Examples: ["tps", "mob_caps", "counter white"]""")
|
||||||
|
public static List<String> defaultLoggers = List.of();
|
||||||
|
|
||||||
|
public static int normalizedTntFuseDuration() {
|
||||||
|
return Math.clamp(tntFuseDuration, 0, Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int normalizedTickCommandPermission() {
|
||||||
|
return Math.clamp(tickCommandPermission, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-7
@@ -13,12 +13,6 @@ public class CommandConfig implements IConfigModule {
|
|||||||
Allow to use tick command""")
|
Allow to use tick command""")
|
||||||
public static boolean tick = false;
|
public static boolean tick = false;
|
||||||
|
|
||||||
@ConfigInfo(name = "datapack_command_enabled", comments =
|
|
||||||
"""
|
|
||||||
Allow to use datapack command
|
|
||||||
--- datapack hot-update unsupported, please restart server""")
|
|
||||||
public static boolean datapack = false;
|
|
||||||
|
|
||||||
@ConfigInfo(name = "function_command_enabled", comments =
|
@ConfigInfo(name = "function_command_enabled", comments =
|
||||||
"""
|
"""
|
||||||
Allow to use function command""")
|
Allow to use function command""")
|
||||||
@@ -28,11 +22,21 @@ public class CommandConfig implements IConfigModule {
|
|||||||
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
|
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
|
||||||
@ConfigInfo(name = "waypoint_command_enabled", comments =
|
@ConfigInfo(name = "waypoint_command_enabled", comments =
|
||||||
"""
|
"""
|
||||||
Allow to use waypoint command""")
|
Allow to use waypoint command and locator bar""")
|
||||||
public static boolean waypoint = false;
|
public static boolean waypoint = false;
|
||||||
|
|
||||||
@ConfigInfo(name = "scoreboard_command_enabled", comments =
|
@ConfigInfo(name = "scoreboard_command_enabled", comments =
|
||||||
"""
|
"""
|
||||||
Allow to use scoreboard command""")
|
Allow to use scoreboard command""")
|
||||||
public static boolean scoreboard = false;
|
public static boolean scoreboard = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "enabled", directory = {"save_all_command"}, comments =
|
||||||
|
"""
|
||||||
|
Allow to use save-all command""")
|
||||||
|
public static boolean saveAll = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"}, comments =
|
||||||
|
"""
|
||||||
|
Log all process of save-all command to console""")
|
||||||
|
public static boolean logAllProcess = false;
|
||||||
}
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package fun.bm.lophine.config.modules.experiment;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(name = "global_entities_counter", category = EnumConfigCategory.EXPERIMENT)
|
||||||
|
public class GlobalEntitiesCounter implements IConfigModule {
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
|
Enable global entities counter.
|
||||||
|
You need to set per-player-mob-spawns to false on paper-world-defaults.yml or paper-world.yml""")
|
||||||
|
public static boolean enabled = false;
|
||||||
|
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "async", comments = "Enable Asynchronous(maybe cause bugs)")
|
||||||
|
public static boolean async = false;
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package fun.bm.lophine.config.modules.experiment;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||||
|
import me.earthme.luminol.config.flags.TransformedConfig;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a config module for redstone in experimental level
|
||||||
|
* If we think configs from here is stable for future, we will move them to function module directory
|
||||||
|
*/
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
|
||||||
|
public class RedStoneConfig implements IConfigModule {
|
||||||
|
@TransformedConfig(name = "enabled", directory = {"experiment", "redstone-ignore-upwards-update"})
|
||||||
|
@ConfigInfo(name = "redstone-ignore-upwards-update", comments = """
|
||||||
|
Should the pre-1.20 mechanism be reintroduced:
|
||||||
|
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
|
||||||
|
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters, and redstone comparators do not check for attachment when receiving status updates from below""")
|
||||||
|
public static boolean redstoneIgnoreUpwardsUpdate = false;
|
||||||
|
|
||||||
|
@TransformedConfig(name = "enabled", directory = {"experiment", "cce-update-suppression"})
|
||||||
|
@ConfigInfo(name = "cce-update-suppression", comments = """
|
||||||
|
Is it permissible to use ClassCastException for update suppression?""")
|
||||||
|
public static boolean cce = false;
|
||||||
|
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "instant-block-updater")
|
||||||
|
public static boolean instantBlockUpdater = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "old-block-remove-behaviour")
|
||||||
|
public static boolean oldBlockRemoveBehaviour = false;
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package fun.bm.lophine.config.modules.fixes;
|
||||||
|
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "update-suppression-crash-fix")
|
||||||
|
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
|
Should crash caused by update suppression be prevented?""")
|
||||||
|
public static boolean enabled = true;
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package fun.bm.lophine.config.modules.function;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ConfigClassInfo(name = "creative_fly_no_clip", category = EnumConfigCategory.FUNCTION)
|
||||||
|
public class CreativeFlyNoClipConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
|
Whether to enable creative fly no clip.
|
||||||
|
When enabled, players in creative mode will not collide with blocks while flying.
|
||||||
|
This allows them to pass through blocks without obstruction.""")
|
||||||
|
public static boolean enabled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
|
||||||
|
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "creativeNoClip", enabled));
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -5,10 +5,12 @@ import me.earthme.luminol.config.IConfigModule;
|
|||||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.leavesmc.leaves.bot.ServerBot;
|
import org.leavesmc.leaves.bot.ServerBot;
|
||||||
import org.leavesmc.leaves.command.bot.BotCommand;
|
import org.leavesmc.leaves.command.bot.BotCommand;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
|
||||||
public class FakeplayerConfig implements IConfigModule {
|
public class FakeplayerConfig implements IConfigModule {
|
||||||
@@ -79,7 +81,6 @@ public class FakeplayerConfig implements IConfigModule {
|
|||||||
@ConfigInfo(name = "enable-locator-bar", comments = """
|
@ConfigInfo(name = "enable-locator-bar", comments = """
|
||||||
Enable locator bar for fakeplayers""")
|
Enable locator bar for fakeplayers""")
|
||||||
public static boolean enableLocatorBar = false;
|
public static boolean enableLocatorBar = false;
|
||||||
|
|
||||||
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
|
public static ServerBot.TickType tickType = ServerBot.TickType.ENTITY_LIST;
|
||||||
|
|
||||||
private BotCommand command = null;
|
private BotCommand command = null;
|
||||||
@@ -91,7 +92,7 @@ public class FakeplayerConfig implements IConfigModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaded(CommentedFileConfig configInstance) {
|
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
command = new BotCommand();
|
command = new BotCommand();
|
||||||
command.register();
|
command.register();
|
||||||
|
|||||||
+8
@@ -24,4 +24,12 @@ public class OldFeatureConfig implements IConfigModule {
|
|||||||
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", directory = {"misc", "revert_raid_changes"}, transformComments = false)
|
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", directory = {"misc", "revert_raid_changes"}, transformComments = false)
|
||||||
@ConfigInfo(name = "old_raid_behavior")
|
@ConfigInfo(name = "old_raid_behavior")
|
||||||
public static boolean oldRaidBehavior = false;
|
public static boolean oldRaidBehavior = false;
|
||||||
|
|
||||||
|
@TransformedConfig(name = "villager-infinite-trade", directory = {"function", "villager"}, transformComments = false)
|
||||||
|
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager"}, transformComments = false)
|
||||||
|
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager-config"}, transformComments = false)
|
||||||
|
@ConfigInfo(name = "villager-void-trade", comments =
|
||||||
|
"""
|
||||||
|
Allow villager void trade.""")
|
||||||
|
public static boolean villagerVoidTrade = false;
|
||||||
}
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package fun.bm.lophine.config.modules.function;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
import fun.bm.lophine.utils.RandomProfilePool;
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.config.flags.HotReloadUnsupported;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "replay-api")
|
||||||
|
public class ReplayAPIConfig implements IConfigModule {
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "enable-cache")
|
||||||
|
public static boolean enableCache = true;
|
||||||
|
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "cache-photographer-time", comments = """
|
||||||
|
Time to cache photographer profile(in seconds)""")
|
||||||
|
public static int cachePhotographerTime = 3600;
|
||||||
|
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "cache-photographer-size", comments = """
|
||||||
|
Maximum size of cache photographer profile""")
|
||||||
|
public static int cachePhotographerSize = 100;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
|
||||||
|
RandomProfilePool.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
package fun.bm.lophine.config.modules.function;
|
|
||||||
|
|
||||||
import me.earthme.luminol.config.IConfigModule;
|
|
||||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
|
||||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
|
||||||
import me.earthme.luminol.config.flags.TransformedConfig;
|
|
||||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
|
||||||
|
|
||||||
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "villager")
|
|
||||||
public class VillagerConfig implements IConfigModule {
|
|
||||||
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager"})
|
|
||||||
@TransformedConfig(name = "villager-infinite-trade", directory = {"misc", "villager-config"})
|
|
||||||
@ConfigInfo(name = "villager-infinite-trade", comments =
|
|
||||||
"""
|
|
||||||
Allow villager infinite trade (limit of 524288 times)
|
|
||||||
---- we won't edit saved data, only edit in send data to client.
|
|
||||||
(after we fixed void trade, this config will drop to void trade)""")
|
|
||||||
public static boolean villagerInfiniteTrade = false;
|
|
||||||
}
|
|
||||||
+4
-1
@@ -7,6 +7,9 @@ import me.earthme.luminol.config.flags.ConfigClassInfo;
|
|||||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
|
||||||
public class WoolHopperCounterConfig implements IConfigModule {
|
public class WoolHopperCounterConfig implements IConfigModule {
|
||||||
@@ -17,7 +20,7 @@ public class WoolHopperCounterConfig implements IConfigModule {
|
|||||||
public static boolean unlimitedSpeed = false;
|
public static boolean unlimitedSpeed = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaded(CommentedFileConfig configInstance) {
|
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> exs) {
|
||||||
if (enabled) new CounterCommand().register();
|
if (enabled) new CounterCommand().register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package fun.bm.lophine.config.modules.function.protocol;
|
||||||
|
|
||||||
|
import fun.bm.lophine.enums.EnumAlternativePlaceType;
|
||||||
|
import me.earthme.luminol.config.IConfigModule;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "alternative_block_placement", directory = {"protocol"})
|
||||||
|
public class AlternativeBlockPlacementProtocolConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
|
Specify the precise placement protocol type
|
||||||
|
NONE Disable precise placement protocol
|
||||||
|
CARPET Precise placement protocol version 2
|
||||||
|
CARPET_FIX Enhanced precise placement protocol version 2 (requires MasaGadget installed on client)
|
||||||
|
LITEMATICA Precise placement protocol version 3""")
|
||||||
|
public static EnumAlternativePlaceType alternativeBlockPlacement = EnumAlternativePlaceType.NONE;
|
||||||
|
|
||||||
|
public static boolean needIgnoreDistance() {
|
||||||
|
return alternativeBlockPlacement != EnumAlternativePlaceType.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+4
-1
@@ -5,8 +5,11 @@ import me.earthme.luminol.config.IConfigModule;
|
|||||||
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||||
import me.earthme.luminol.enums.EnumConfigCategory;
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.leavesmc.leaves.protocol.syncmatica.SyncmaticaProtocol;
|
import org.leavesmc.leaves.protocol.syncmatica.SyncmaticaProtocol;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "syncmatica", directory = {"protocol"})
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "syncmatica", directory = {"protocol"})
|
||||||
public class SyncmaticaProtocolConfig implements IConfigModule {
|
public class SyncmaticaProtocolConfig implements IConfigModule {
|
||||||
@ConfigInfo(name = "enabled", comments = """
|
@ConfigInfo(name = "enabled", comments = """
|
||||||
@@ -19,7 +22,7 @@ public class SyncmaticaProtocolConfig implements IConfigModule {
|
|||||||
Maximum Projection File Size (in bytes)""")
|
Maximum Projection File Size (in bytes)""")
|
||||||
public static int quotaLimit = 40000000;
|
public static int quotaLimit = 40000000;
|
||||||
|
|
||||||
public void onLoaded(CommentedFileConfig configInstance) {
|
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
|
||||||
SyncmaticaProtocol.init(enabled);
|
SyncmaticaProtocol.init(enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package fun.bm.lophine.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.config.flags.HotReloadUnsupported;
|
||||||
|
import me.earthme.luminol.enums.EnumConfigCategory;
|
||||||
|
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "waypoint")
|
||||||
|
public class WayPointOptimizedTableConfig implements IConfigModule {
|
||||||
|
@HotReloadUnsupported
|
||||||
|
@ConfigInfo(name = "optimizedTable", comments = """
|
||||||
|
Should use optimized table instead of normal concurrent table for waypoints.
|
||||||
|
May improve performance when there are many waypoints and players.
|
||||||
|
When enabled, more memory is needed to store data.""")
|
||||||
|
public static boolean optimizedTable = false;
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
|
|||||||
|
|
||||||
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
|
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
|
||||||
public class RemovedConfig implements IConfigModule {
|
public class RemovedConfig implements IConfigModule {
|
||||||
|
@TransformedConfig(name = "datapack_command_enabled", directory = {"experiment", "command"}, transform = false)
|
||||||
@TransformedConfig(name = "disable_end_crystal_check", directory = {"fixes", "end_crystal"}, transform = false)
|
@TransformedConfig(name = "disable_end_crystal_check", directory = {"fixes", "end_crystal"}, transform = false)
|
||||||
@TransformedConfig(name = "disable_end_crystal_check", directory = {"misc", "end_crystal"}, transform = false)
|
@TransformedConfig(name = "disable_end_crystal_check", directory = {"misc", "end_crystal"}, transform = false)
|
||||||
@TransformedConfig(name = "allow_skip_cooldown", directory = {"misc", "revert_raid_changes"}, transform = false)
|
@TransformedConfig(name = "allow_skip_cooldown", directory = {"misc", "revert_raid_changes"}, transform = false)
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package fun.bm.lophine.enums;
|
||||||
|
|
||||||
|
public enum EnumAlternativePlaceType {
|
||||||
|
NONE,
|
||||||
|
CARPET,
|
||||||
|
CARPET_FIX,
|
||||||
|
LITEMATICA
|
||||||
|
}
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
package fun.bm.lophine.protocol;
|
||||||
|
|
||||||
|
import fun.bm.lophine.carpet.config.modules.GeneralCompatConfig;
|
||||||
|
import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
import io.papermc.paper.threadedregions.RegionizedWorldData;
|
||||||
|
import io.papermc.paper.threadedregions.TickRegionScheduler;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundTabListPacket;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.ServerTickRateManager;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.entity.MobCategory;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.NaturalSpawner;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||||
|
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||||
|
import org.leavesmc.leaves.util.HopperCounter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@LeavesProtocol.Register(namespace = "carpet")
|
||||||
|
public class CarpetLoggerProtocol implements LeavesProtocol {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger("CarpetLoggerProtocol");
|
||||||
|
private static final Map<String, Map<String, String>> PLAYER_SUBSCRIPTIONS = new ConcurrentHashMap<>();
|
||||||
|
private static volatile Map<String, String> configuredSubscriptions = null;
|
||||||
|
|
||||||
|
public static void refreshConfiguredDefaults(boolean initial) {
|
||||||
|
Map<String, String> defaults = parseConfiguredDefaults(GeneralCompatConfig.defaultLoggers);
|
||||||
|
configuredSubscriptions = defaults;
|
||||||
|
if (defaults == null || defaults.isEmpty()) {
|
||||||
|
PLAYER_SUBSCRIPTIONS.clear();
|
||||||
|
if (initial) return;
|
||||||
|
for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
||||||
|
clearHud(player);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PLAYER_SUBSCRIPTIONS.replaceAll((playerName, ignored) -> defaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String serializeConfiguredDefaults(List<String> configuredLoggers) {
|
||||||
|
List<String> serialized = new ArrayList<>();
|
||||||
|
if (configuredLoggers != null) {
|
||||||
|
for (String entry : configuredLoggers) {
|
||||||
|
if (entry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String trimmed = entry.trim();
|
||||||
|
if (!trimmed.isEmpty()) {
|
||||||
|
serialized.add(trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return serialized.isEmpty() ? "none" : String.join(",", serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtocolHandler.PlayerJoin
|
||||||
|
public static void onPlayerJoin(ServerPlayer player) {
|
||||||
|
if (configuredSubscriptions != null && !configuredSubscriptions.isEmpty()) {
|
||||||
|
PLAYER_SUBSCRIPTIONS.putIfAbsent(player.getScoreboardName(), configuredSubscriptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtocolHandler.PlayerLeave
|
||||||
|
public static void onPlayerLeave(ServerPlayer player) {
|
||||||
|
clearHud(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProtocolHandler.Ticker(tickerId = "hud")
|
||||||
|
public static void onHudTick() {
|
||||||
|
if (PLAYER_SUBSCRIPTIONS.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MinecraftServer server = MinecraftServer.getServer();
|
||||||
|
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
|
||||||
|
Map<String, String> subscriptions = PLAYER_SUBSCRIPTIONS.get(player.getScoreboardName());
|
||||||
|
if (subscriptions == null || subscriptions.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
player.getBukkitEntity().taskScheduler.schedule((LivingEntity livingEntity) -> {
|
||||||
|
if (livingEntity instanceof ServerPlayer scheduledPlayer) {
|
||||||
|
sendHud(server, scheduledPlayer, subscriptions);
|
||||||
|
}
|
||||||
|
}, null, 1L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int tickerInterval(String tickerID) {
|
||||||
|
return "hud".equals(tickerID) ? 20 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendHud(MinecraftServer server, ServerPlayer player, Map<String, String> subscriptions) {
|
||||||
|
List<net.minecraft.network.chat.Component> lines = new ArrayList<>();
|
||||||
|
subscriptions.forEach((loggerName, option) -> {
|
||||||
|
switch (loggerName) {
|
||||||
|
case "tps" -> lines.add(buildTpsLine(server));
|
||||||
|
case "mobcaps" -> {
|
||||||
|
net.minecraft.network.chat.Component line = buildMobcapsLine(player, option);
|
||||||
|
if (line != null) {
|
||||||
|
lines.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "counter" -> lines.addAll(buildCounterLines(server, player.level(), option));
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MutableComponent footer = net.minecraft.network.chat.Component.empty();
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
footer.append(net.minecraft.network.chat.Component.literal("\n"));
|
||||||
|
}
|
||||||
|
footer.append(lines.get(i));
|
||||||
|
}
|
||||||
|
player.connection.send(new ClientboundTabListPacket(net.minecraft.network.chat.Component.empty(), footer));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void clearHud(ServerPlayer player) {
|
||||||
|
player.connection.send(new ClientboundTabListPacket(net.minecraft.network.chat.Component.empty(), net.minecraft.network.chat.Component.empty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static net.minecraft.network.chat.Component buildTpsLine(MinecraftServer server) {
|
||||||
|
ServerTickRateManager tickManager = server.tickRateManager();
|
||||||
|
io.papermc.paper.threadedregions.TickData.TickReportData tickData = TickRegionScheduler.getCurrentRegion().getData().getRegionSchedulingHandle().getTickReport5s(System.nanoTime());
|
||||||
|
final double tps = tickData.tpsData().segmentAll().average();
|
||||||
|
final double mspt = tickData.timePerTickData().segmentAll().average() / 1.0E6;
|
||||||
|
|
||||||
|
ChatFormatting color = heatmapColor(mspt, tickManager.millisecondsPerTick());
|
||||||
|
return net.minecraft.network.chat.Component.empty()
|
||||||
|
.append(net.minecraft.network.chat.Component.literal("TPS: ").withStyle(ChatFormatting.GRAY))
|
||||||
|
.append(net.minecraft.network.chat.Component.literal(String.format(Locale.US, "%.1f", tps)).withStyle(color))
|
||||||
|
.append(net.minecraft.network.chat.Component.literal(" MSPT: ").withStyle(ChatFormatting.GRAY))
|
||||||
|
.append(net.minecraft.network.chat.Component.literal(String.format(Locale.US, "%.1f", mspt)).withStyle(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static net.minecraft.network.chat.Component buildMobcapsLine(ServerPlayer player, String option) {
|
||||||
|
final ServerLevel level = resolveMobcapsLevel(player, option);
|
||||||
|
if (level == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegionizedWorldData data = level.getCurrentWorldData();
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final NaturalSpawner.SpawnState spawnState = data.lastSpawnState;
|
||||||
|
if (spawnState == null) {
|
||||||
|
return net.minecraft.network.chat.Component.literal("Mobcaps: unavailable").withStyle(ChatFormatting.DARK_GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int chunks = spawnState.getSpawnableChunkCount();
|
||||||
|
var counts = spawnState.getMobCategoryCounts();
|
||||||
|
MutableComponent line = net.minecraft.network.chat.Component.literal("Mobcaps").withStyle(ChatFormatting.GRAY);
|
||||||
|
for (MobCategory category : MobCategory.values()) {
|
||||||
|
if (category == MobCategory.MISC) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int current = counts.getOrDefault(category, 0);
|
||||||
|
int limit = NaturalSpawner.globalLimitForCategory(level, category, chunks);
|
||||||
|
line.append(net.minecraft.network.chat.Component.literal(" " + shortName(category) + " ").withStyle(ChatFormatting.DARK_GRAY));
|
||||||
|
line.append(net.minecraft.network.chat.Component.literal(current + "/" + limit).withStyle(categoryColor(current, limit)));
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<net.minecraft.network.chat.Component> buildCounterLines(MinecraftServer server, Level level, String option) {
|
||||||
|
List<net.minecraft.network.chat.Component> lines = new ArrayList<>();
|
||||||
|
String colors = option == null || option.isBlank() ? "white" : option;
|
||||||
|
for (String rawColor : colors.split(",")) {
|
||||||
|
String colorName = rawColor.trim();
|
||||||
|
if (colorName.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DyeColor color = DyeColor.byName(colorName, null);
|
||||||
|
if (color == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
HopperCounter counter = HopperCounter.getCounter(color);
|
||||||
|
if (counter == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (Component component : counter.format(server, level, false)) {
|
||||||
|
lines.add(PaperAdventure.asVanilla(component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerLevel resolveMobcapsLevel(ServerPlayer player, String option) {
|
||||||
|
if (option == null || option.isBlank() || option.equalsIgnoreCase("dynamic")) {
|
||||||
|
return player.level();
|
||||||
|
}
|
||||||
|
return switch (option.toLowerCase(Locale.ROOT)) {
|
||||||
|
case "overworld" -> player.level().dimension() == Level.OVERWORLD ? player.level() : null;
|
||||||
|
case "nether" -> player.level().dimension() == Level.NETHER ? player.level() : null;
|
||||||
|
case "end" -> player.level().dimension() == Level.END ? player.level() : null;
|
||||||
|
default -> player.level();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChatFormatting heatmapColor(double actual, double reference) {
|
||||||
|
if (actual > reference) {
|
||||||
|
return ChatFormatting.LIGHT_PURPLE;
|
||||||
|
}
|
||||||
|
if (actual > 0.8D * reference) {
|
||||||
|
return ChatFormatting.RED;
|
||||||
|
}
|
||||||
|
if (actual > 0.5D * reference) {
|
||||||
|
return ChatFormatting.YELLOW;
|
||||||
|
}
|
||||||
|
if (actual >= 0.0D) {
|
||||||
|
return ChatFormatting.DARK_GREEN;
|
||||||
|
}
|
||||||
|
return ChatFormatting.GRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChatFormatting categoryColor(int current, int limit) {
|
||||||
|
if (limit <= 0) {
|
||||||
|
return ChatFormatting.DARK_GRAY;
|
||||||
|
}
|
||||||
|
double ratio = current / (double) limit;
|
||||||
|
if (ratio >= 1.0D) {
|
||||||
|
return ChatFormatting.RED;
|
||||||
|
}
|
||||||
|
if (ratio >= 0.8D) {
|
||||||
|
return ChatFormatting.YELLOW;
|
||||||
|
}
|
||||||
|
return ChatFormatting.GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String shortName(MobCategory category) {
|
||||||
|
return switch (category) {
|
||||||
|
case MONSTER -> "M";
|
||||||
|
case CREATURE -> "C";
|
||||||
|
case AMBIENT -> "A";
|
||||||
|
case AXOLOTLS -> "Ax";
|
||||||
|
case UNDERGROUND_WATER_CREATURE -> "UWC";
|
||||||
|
case WATER_CREATURE -> "WC";
|
||||||
|
case WATER_AMBIENT -> "WA";
|
||||||
|
case MISC -> "X";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> parseConfiguredDefaults(List<String> configuredLoggers) {
|
||||||
|
LinkedHashMap<String, String> subscriptions = new LinkedHashMap<>();
|
||||||
|
if (configuredLoggers == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (String entry : configuredLoggers) {
|
||||||
|
if (entry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (String chunk : entry.split(",")) {
|
||||||
|
String token = chunk.trim();
|
||||||
|
if (token.isEmpty() || token.equalsIgnoreCase("none")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] parts = token.split("\\s+", 2);
|
||||||
|
String loggerName = parts[0].toLowerCase(Locale.ROOT);
|
||||||
|
if (!isSupported(loggerName)) {
|
||||||
|
LOGGER.debug("Ignoring unsupported Carpet default logger '{}'", loggerName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String option = parts.length == 1 ? defaultOption(loggerName) : parts[1].trim();
|
||||||
|
if (option.isEmpty()) {
|
||||||
|
option = defaultOption(loggerName);
|
||||||
|
}
|
||||||
|
subscriptions.put(loggerName, option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subscriptions.isEmpty() ? null : Map.copyOf(subscriptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isSupported(String loggerName) {
|
||||||
|
return Arrays.asList("tps", "mobcaps", "counter").contains(loggerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull String defaultOption(String loggerName) {
|
||||||
|
return switch (loggerName) {
|
||||||
|
case "mobcaps" -> "dynamic";
|
||||||
|
case "counter" -> "white";
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user