Compare commits

..

32 Commits

Author SHA1 Message Date
Helvetica Volubi 94e7c4e822 Update Upstream(Luminol) 2025-07-26 00:01:35 +08:00
Helvetica Volubi 01582648ee feat: add flipping shears support(#29)
Co-authored-by: violetc <58360096+s-yh-china@users.noreply.github.com>
2025-07-23 20:30:45 +08:00
Helvetica Volubi db9bd6e469 Update Upstream(Luminol) 2025-07-23 19:30:21 +08:00
Helvetica Volubi 0eebea7a21 Update Upstream(Luminol) 2025-07-20 13:16:27 +08:00
Helvetica Volubi 1707673c8d feat: add missing command for unsafe waypoint
Update Upstream(Luminol)
2025-07-18 22:15:13 +08:00
Bacteriawa 7179463c36 Start 1.21.8 2025-07-18 19:19:55 +08:00
Bacteriawa 509e782d1a Update Upstream(Luminol) 2025-07-18 16:58:46 +08:00
Helvetica Volubi bfb5f74600 fix: fix a config name error 2025-07-17 21:43:24 +08:00
Helvetica Volubi a697b179e7 Update Upstream(Luminol) 2025-07-17 00:37:28 +08:00
Helvetica Volubi 904abaa564 Update Upstream(Luminol) 2025-07-16 00:12:42 +08:00
Bacteriawa d1aeaa83f4 Update Upstream(Lumniol) 2025-07-13 22:26:19 +08:00
Helvetica Volubi 145eae3c41 refactor: push update to upstream 2025-07-13 02:53:40 +08:00
Helvetica Volubi 6e61e12285 Update upstream(Luminol) 2025-07-12 14:56:28 +08:00
Klop233 56e870d999 Update Upstream(Luminol) 2025-07-11 11:09:37 +00:00
Helvetica Volubi 7f8135b193 fix: fix #26 & Update upstream(Luminol) 2025-07-10 03:10:32 +08:00
Helvetica Volubi 31096e1a48 Add config to enable unsafe waypoint bar 2025-07-07 18:25:45 +08:00
Helvetica Volubi f261b9fe58 feat: add config to allow infinite trade 2025-07-07 16:40:42 +08:00
Helvetica Volubi 92412e0a72 feat: add Old Explosion Damage Calculator support(#25)
Co-authored by: MC_XiaoHei <xor7xiaohei@gmail.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e96b237749a960f297f211d439ffc9ea7fd2381/leaves-server/minecraft-patches/features/0134-Old-wet-tnt-explode-behavior.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
2025-07-07 15:37:26 +08:00
Helvetica Volubi 23f4d70fca Update Upstream(Luminol) 2025-07-07 01:19:23 +08:00
Helvetica Volubi c613aaa191 fix: fix a bug in datapack reload - hot reload unsupported 2025-07-05 18:51:35 +08:00
Helvetica Volubi 692c38f7ac Update upstream(Luminol) 2025-07-04 18:21:23 +08:00
Helvetica Volubi 96683209f5 Add config to enable datapack command - only support some function 2025-07-03 00:36:15 +08:00
Helvetica Volubi 6d9458fa01 Update Upstream(Luminol) 2025-07-02 23:31:19 +08:00
Helvetica Volubi 333a7fc17c Update to 1.21.7 2025-07-01 21:54:38 +08:00
Helvetica Volubi 914d8cc1dd remove Better ShulkerBox and Update Upstream(Luminol) 2025-06-30 13:51:32 +08:00
Helvetica Volubi 6f9e4abcbf Start 1.21.6 2025-06-28 00:41:56 +08:00
Helvetica Volubi 986cce555c fix: refix spawnInvulnerableTime 2025-06-27 21:07:37 +08:00
Helvetica Volubi 34cc8765c6 fix: fix some bugs 2025-06-24 19:56:14 +08:00
Helvetica Volubi a5393833e8 Update Upstream (Luminol)
use our own bState
2025-06-20 00:57:28 +08:00
Helvetica Volubi 878ee153ef fix: fix up Shulker box (#11) (#12) 2025-06-18 20:03:37 +08:00
Helvetica Volubi 71455cca64 feat: old replaceable by mushrooms (#10)
Update upstream (Luminol)
2025-06-18 16:50:23 +08:00
Helvetica Volubi 16f2258eed fix: try fix shulker box clear bug(#5) 2025-06-17 14:51:51 +08:00
66 changed files with 1598 additions and 1748 deletions
@@ -1,10 +1,12 @@
name: Lophine CI - ver/1.21.5
name: Lophine CI
on:
push:
branches: [ "ver/1.21.5" ]
branches:
- "**"
pull_request:
branches: [ "ver/1.21.5" ]
branches:
- "**"
permissions: write-all
@@ -20,7 +22,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 22
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
@@ -32,15 +34,15 @@ jobs:
run: git config --global user.email "ci@luminolmc.com" && git config --global user.name "LuminolMC CI"
- name: Apply All Patches
run: ./gradlew applyAllPatches
run: ./gradlew --refresh-dependencies applyAllPatches
- name: CreateMojmapPaperclipJar
run: ./gradlew createMojmapPaperclipJar
run: ./gradlew --refresh-dependencies createMojmapPaperclipJar
- name: Publish to repo
if: github.event_name != 'pull_request' && false # do not push to any repo
continue-on-error: true
run: ./gradlew generateDevelopmentBundle publish -PpublishDevBundle=true
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
env:
PRIVATE_MAVEN_REPO_PASSWORD: ${{ secrets.PRIVATE_MAVEN_REPO_PASSWORD }}
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
+1 -2
View File
@@ -74,8 +74,7 @@ dependencies {
可查看 [Contributing](./docs/CONTRIBUTING.md)
## BStats
Temporarily use Luminol's.
![bStats](https://bstats.org/signatures/server-implementation/Luminol.svg "bStats")
![bStats](https://bstats.org/signatures/server-implementation/Lophine.svg "bStats")
## 特别感谢
<b>感谢[LegacyLands](https://github.com/LegacyLands)对本项目的赞助,如果你想开发一些跨folia/非folia平台的插件,[legacy-lands-library](https://github.com/LegacyLands/legacy-lands-library/)将会是个不错的lib</b>
+1 -2
View File
@@ -73,8 +73,7 @@ When you meet any problems, just ask us, we will do our best to solve it, but re
See [Contributing](./docs/CONTRIBUTING_EN.md)
## BStats
Temporarily use Luminol's.
![bStats](https://bstats.org/signatures/server-implementation/Luminol.svg "bStats")
![bStats](https://bstats.org/signatures/server-implementation/Lophine.svg "bStats")
## Special Thanks
Thanks [LegacyLands](https://github.com/LegacyLands) for sponsoring this project.If you want to develop some crossing folia/non-folia platform plugins, [legacy-lands-library](https://github.com/LegacyLands/legacy-lands-library/) will be a nice choice for you
+10 -9
View File
@@ -3,7 +3,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins {
java // TODO java launcher tasks
id("io.papermc.paperweight.patcher") version "2.0.0-beta.17"
id("moe.luminolmc.hyacinthusweight.patcher") version "+" // Automatically pulls the latest
}
paperweight {
@@ -41,6 +41,7 @@ paperweight {
}
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
val menthaMavenPublicUrl = "https://repo.menthamc.com/repository/maven-public/";
subprojects {
apply(plugin = "java-library")
@@ -55,6 +56,7 @@ subprojects {
repositories {
mavenCentral()
maven(paperMavenPublicUrl)
maven(menthaMavenPublicUrl)
}
dependencies {
@@ -65,16 +67,15 @@ subprojects {
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
tasks.withType<JavaCompile> {
tasks.withType<JavaCompile>().configureEach {
options.encoding = Charsets.UTF_8.name()
options.release = 21
options.isFork = true
options.forkOptions.memoryMaximumSize = "6g" // Prevent OOM during building
}
tasks.withType<Javadoc> {
tasks.withType<Javadoc>().configureEach {
options.encoding = Charsets.UTF_8.name()
}
tasks.withType<ProcessResources> {
tasks.withType<ProcessResources>().configureEach {
filteringCharset = Charsets.UTF_8.name()
}
tasks.withType<Test> {
@@ -90,14 +91,14 @@ subprojects {
maven("https://repo.menthamc.com/repository/maven-snapshots/") {
name = "MenthaMC"
credentials(PasswordCredentials::class) {
username = System.getenv("MAVEN_REPO_USER")
password = System.getenv("MAVEN_REPO_PASSWORD")
username = System.getenv("PRIVATE_MAVEN_REPO_USERNAME")
password = System.getenv("PRIVATE_MAVEN_REPO_PASSWORD")
}
}
}
}
tasks.withType<Javadoc> {
tasks.withType<Javadoc>().configureEach {
options {
(this as StandardJavadocDocletOptions).apply {
addStringOption("-add-modules", "jdk.incubator.vector")
@@ -105,4 +106,4 @@ subprojects {
}
}
}
}
}
+7 -5
View File
@@ -41,19 +41,21 @@ Lophine 使用和 Folia 一样的补丁系统,并为了针对不同部分的
1. 将你的仓库 clone 到本地;
2. 在你的 IDE 或 终端 内执行 Gradle 的 `applyAllPatches` 任务,如果是在终端内,你可以执行 `./gradlew applyAllPatches`
3. 在执行操作后,仓库根目录下应该存在以下目录对: `lophine-api``lophine-server` `folia-api``folia-server` 以及 `paper-api``paper-server`(下文称作 `*-api``*-server` );
3. 在执行操作后,仓库根目录下应该存在以下目录对: `lophine-api``lophine-server` `luminol-api``luminol-server` `folia-api``folia-server` 以及 `paper-api``paper-server`(下文称作 `*-api``*-server` );
4. 进入 仓库根目录下的 `*-api``*-server` 文件夹进行修改。
以下为对上述各个文件夹的简单描述,详细描述可以参考[这里](https://github.com/Toffikk/paperweight-examples/blob/18241979c88068d5b061d95ad69c98ecb201c246/README.md)
1. API部分
- `lophine-api` 暂无有效文件
- `lophine-api` 对新增API的修改
- `luminol-api` :对luminol-API的修改应当在此文件夹下进行
- `folia-api` :对folia-API的修改应当在此文件夹下进行
- `paper-api` :对paper-API/spigot-API/bukkit-API的修改应该在此文件夹下进行
2. Server部分
- `lophine-server` :对Minecraft原版服务器的修改应当在此文件夹下进行
- `folia-server` 暂无有效文件
- `paper-server` :对于非原版的对服务器逻辑的修改应当在此文件夹下进行
- `lophine-server` :对Minecraft原版服务器的修改和新增文件应当在此文件夹下进行
- `luminol-server` 对luminol-server的修改应当在此文件夹下进行
- `folia-server` :对folia-Server的修改应当在此文件夹下进行
- `paper-server` :对于paper对服务器逻辑的修改应当在此文件夹下进行
顺便一提,仓库根目录下的 `*-api``*-server` 并不是正常的 git 仓库:
+7 -5
View File
@@ -44,20 +44,22 @@ If you have forked the main repository, then you should follow the steps below:
1. Clone your repository to local
2. Run Gradle's `applyAllPatches` task in your IDE or terminal (You can run `./gradlew applyAllPatches` directly in terminal.)
3. After performing the operation, the following directory pairs should exist in the root directory of the warehouse: `lophine-api` and `lophine-server` , `folia-api` and `folia-server` , `paper-api` and `paper-server` (Referred to `*-api` and `*-server` as below)
3. After performing the operation, the following directory pairs should exist in the root directory of the warehouse: `lophine-api` and `lophine-server` , `luminol-api` and `luminol-server` , `folia-api` and `folia-server` , `paper-api` and `paper-server` (Referred to `*-api` and `*-server` as below)
4. Enter `*-api` and `*-server` directory to carry out modifications.
The following is the simple description of the aforementioned folders, detailed description can be referred to [here](https://github.com/Toffikk/paperweight-examples/blob/18241979c88068d5b061d95ad69c98ecb201c246/README.md):
1. API part
- `lophine-api` : There is no valid file
- `lophine-api` : Modifications to the new API
- `luminol-api` : Modifications to Luminol API should be carried out in this folder
- `folia-api` : Modifications to Folia API should be carried out in this folder
- `paper-api` : Modifications to Paper API/Spigot API/Bukkit API should be carried out in this folder
2. Server part
- `lophine-server` : Modifications to Minecraft Vanilla Server's source logic should be carried out in this folder
- `folia-server` : There is no valid file
- `paper-server` : Modifications to non-vanilla server logic should be carried out in this folder
- `lophine-server` : Changes and new files to the Minecraft vanilla server should be made in this folder
- `luminol-server` : Changes to luminol-server should be made in this folder
- `folia-server` : Changes to folia-server should be made in this folder
- `paper-server` : Modifications to the server logic for paper should be made in this folder
BTW, `*-api` and `*-server` and are not normal git repositories.
+6 -4
View File
@@ -1,8 +1,10 @@
group=me.earthme.lophine
version=1.21.5-R0.1-SNAPSHOT
mcVersion=1.21.5
group=fun.bm.lophine
version=1.21.8-R0.1-SNAPSHOT
mcVersion=1.21.8
release=2
# 0 for skip release, 1 for pre-release, 2 for release
luminolRef=784ce10986c214df322a9289e8ddb0b700759596
luminolRef=5d95e9675c4cc0d74d791c09f22c0b990ad55bcf
org.gradle.configuration-cache=true
org.gradle.caching=true
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+16 -7
View File
@@ -1,6 +1,6 @@
--- a/luminol-server/build.gradle.kts
+++ b/luminol-server/build.gradle.kts
@@ -54,7 +_,23 @@
@@ -52,7 +_,23 @@
}
}
@@ -23,8 +23,8 @@
+
+ activeFork = lophine
spigot {
buildDataRef = "702e1a0a5072b2c4082371d5228cb30525687efc"
@@ -142,12 +_,16 @@
resources { srcDir("../paper-server/src/main/resources") }
java { srcDir("../folia-server/src/main/java") }
@@ -47,11 +47,11 @@
dependencies {
- implementation(project(":luminol-api")) // Luminol
+ implementation(project(":lophine-api")) // Luminol // Lophine
implementation("com.electronwill.night-config:toml:3.8.2") // Luminol - Night config
// Abomination start
+ implementation(project(":lophine-api")) // Lophine
// Luminol start - Dependenices insert
implementation("com.electronwill.night-config:toml:3.8.2") // Night config
implementation("com.github.luben:zstd-jni:1.5.4-1")
@@ -264,14 +_,14 @@
@@ -277,14 +_,14 @@
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
@@ -62,7 +62,7 @@
- "Specification-Title" to "Luminol",
+ "Specification-Title" to "Lophine",
"Specification-Version" to project.version,
"Specification-Vendor" to "Luminol Team",
"Specification-Vendor" to "LuminolMC org",
- "Brand-Id" to "luminolmc:luminol",
- "Brand-Name" to "Luminol",
+ "Brand-Id" to "luminolmc:lophine",
@@ -70,3 +70,12 @@
"Build-Number" to (build ?: ""),
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
@@ -448,7 +_,7 @@
}
fill {
- project("luminol")
+ project("lophine")
versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") })
version(paperweight.minecraftVersion)
@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 8 Jun 2025 00:58:13 +0800
Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index 26a812cd526acfd1edf31a5c9799fa6deeae927a..9b01cf6f066b2998a2b178321782be1c96f73b0c 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -19,6 +19,7 @@ public class ConfigManager {
public static void initConfigs() throws IOException {
configfiles.put("luminol", new ConfigsInstance(new File("luminol_config"), "luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", new ConfigsInstance(new File("lophine_config"), "lophine", "fun.bm.lophine.config.modules")); // add lophine config to global config
preLoad();
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
index 531214d7ab28ece4bf84e82b39d1c9f983f0fb0c..b68fa0427bb975e91e76f73ab4cc089a424937a3 100644
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java
@@ -5,6 +5,7 @@ import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class CommandBlockExecutionConfig implements IConfigModule {
+ @me.earthme.luminol.config.flags.TransformedConfig(name = "command_block_enabled", category = {"experiment", "command"}, originInstance = "lophine")
@ConfigInfo(baseName = "enabled")
public static boolean enabled = false;
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 100644
--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo;
public class ServerModNameConfig implements IConfigModule {
@ConfigInfo(baseName = "name")
- public static String serverModName = "Luminol";
+ public static String serverModName = "Lophine";
@ConfigInfo(baseName = "vanilla_spoof")
public static boolean fakeVanilla = false;
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to disable end crystal check
diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..d62a9e93dae7b4a7a079e73e80e68e6a81b4c437 100644
index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..4fb9244172b74c3c5fed984d5d3b968f76dd12be 100644
--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -547,6 +547,8 @@ public class EndDragonFight {
@@ -13,7 +13,7 @@ index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..d62a9e93dae7b4a7a079e73e80e68e6a
blockPos = this.portalLocation;
}
+ // Luminol start - Disable end crystal check
+ if (!me.earthme.lophine.config.modules.misc.DisableEndCrystalCheckConfig.disableCheck) {
+ if (!fun.bm.lophine.config.modules.misc.DisableEndCrystalCheckConfig.disableCheck) {
// Paper start - Perf: Do crystal-portal proximity check before entity lookup
if (placedEndCrystalPos != null) {
// The end crystal must be 0 or 1 higher than the portal origin
@@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 8 Jun 2025 00:58:12 +0800
Subject: [PATCH] Rebrand to Lophine
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
index fcf599846a38beeb8f094d5376c01d5a690f7a2f..a70c04dc72a15e4e8de8de677951f1eb605057b0 100644
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -108,7 +108,7 @@ public class Main {
JvmProfiler.INSTANCE.start(Environment.SERVER);
}
- me.earthme.luminol.config.LuminolConfig.preLoadConfig(); // Luminol - Luminol config
+ me.earthme.lophine.config.LophineConfig.initConfigs(); // Lophine - Lophine config
io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper
Bootstrap.bootStrap();
Bootstrap.validate();
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 5290b9cb524160717fb40704fb10fc0d0a37941b..ba0cdba050cd3bf9231e15dd9543d34f37d9dae5 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -171,8 +171,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
// Paper end - initialize global and world-defaults configuration
- me.earthme.luminol.config.LuminolConfig.finalizeLoadConfig(); //Luminol - load config file
- me.earthme.luminol.config.LuminolConfig.setupLatch(); //Luminol - load config file
+ me.earthme.lophine.config.LophineConfig.loadConfigFiles(); //Luminol - load config file // Lophine - load config file
if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
if (this.convertOldUsers()) {
@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:36:31 +0800
Subject: [PATCH] Add config for command block command execution
diff --git a/net/minecraft/world/level/BaseCommandBlock.java b/net/minecraft/world/level/BaseCommandBlock.java
index 91e30f9c83259abc0589f4ee69c429cd4305d6ea..8155da15908fd944d452fd6aaff69cfdfcc7b36b 100644
--- a/net/minecraft/world/level/BaseCommandBlock.java
+++ b/net/minecraft/world/level/BaseCommandBlock.java
@@ -102,7 +102,7 @@ public abstract class BaseCommandBlock implements CommandSource {
}
public boolean performCommand(Level level) {
- if (true) return false; // Folia - region threading
+ if (!me.earthme.lophine.config.modules.experiment.CommandConfig.block) return false; // Folia - region threading // Luminol
if (level.isClientSide || level.getGameTime() == this.lastExecution) {
return false;
} else if ("Searge".equalsIgnoreCase(this.command)) {
@@ -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
index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530c547ac19 100644
index e1842ab8f20271a8b20ab8462b09a4745a612a9a..8405157ec35a443e238fa6866772c839621d73d7 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -299,6 +299,11 @@ public final class RegionizedServer {
@@ -13,19 +13,19 @@ index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530
*/
++this.tickCount;
+ // Luminol start - Add a config to enable tick command
+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.tick();
+ }
+ // Luminol end - Add a config to enable tick command
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue((int)this.tickCount);
@@ -321,6 +326,13 @@ public final class RegionizedServer {
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -322,6 +327,13 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Luminol start - Add a config to enable tick command
+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.reduceSprintTicks();
+ MinecraftServer.tickRateManager.endTickWork();
+ }
@@ -34,17 +34,17 @@ index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530
// tick connections
this.tickConnections();
@@ -454,7 +466,7 @@ public final class RegionizedServer {
@@ -455,7 +467,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final int tickCount) {
- if (world.tickTime) {
+ if ((!me.earthme.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
+ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
if (world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
world.setDayTime(world.levelData.getDayTime() + (long)tickCount);
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index fa6b8d756195c1b430cc11214a901bd42eebc98d..1d79465c9b04c5cdfd299278786916cb10e49522 100644
index 0357792de0ed8ec9058d1847c8b45c33ff365af6..4945c11f573a53df2f5be4beb7af6a3f4d32f7d4 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -31,8 +31,8 @@ public final class TickRegionScheduler {
@@ -58,7 +58,7 @@ index fa6b8d756195c1b430cc11214a901bd42eebc98d..1d79465c9b04c5cdfd299278786916cb
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
@@ -375,8 +375,23 @@ public final class TickRegionScheduler {
@@ -394,8 +394,23 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
@@ -66,7 +66,7 @@ index fa6b8d756195c1b430cc11214a901bd42eebc98d..1d79465c9b04c5cdfd299278786916cb
- final int tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Luminol start - Add a config to enable tick command
+ final int tickCount;
+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
@@ -84,12 +84,12 @@ index fa6b8d756195c1b430cc11214a901bd42eebc98d..1d79465c9b04c5cdfd299278786916cb
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
@@ -416,6 +431,11 @@ public final class TickRegionScheduler {
@@ -435,6 +450,11 @@ public final class TickRegionScheduler {
try {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
+ // Luminol start - Add a config to enable tick command
+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ MinecraftServer.tickRateManager.endTickWork();
+ }
+ // Luminol end - Add a config to enable tick command
@@ -97,16 +97,16 @@ index fa6b8d756195c1b430cc11214a901bd42eebc98d..1d79465c9b04c5cdfd299278786916cb
this.scheduler.regionFailed(this, false, thr);
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index ea50e3c0c4044f03dc8257680814f808fbf3a177..bd5d8bbb667585c1bf976e2eaa38f2b72eabe9e2 100644
index 8a90aa5c145f53afbb3f2371f97cb09974f30bbb..0d5ed9602492c8393088954105e9a19032067b8b 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -214,7 +214,11 @@ public class Commands {
@@ -243,7 +243,11 @@ public class Commands {
TeleportCommand.register(this.dispatcher);
TellRawCommand.register(this.dispatcher, context);
//TestCommand.register(this.dispatcher, context); // Folia - region threading
- //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Luminol start - Add a config to enable tick command
+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) {
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) {
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Luminol end - Add a config to enable tick command
@@ -114,10 +114,10 @@ index ea50e3c0c4044f03dc8257680814f808fbf3a177..bd5d8bbb667585c1bf976e2eaa38f2b7
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 33d596c0f07d076886c0dd8eb93e901cdb56e438..87625b365e04ce05fa2b6cdf2003c839255c4393 100644
index 2ed2f4cca3a81117c0beaf7a11bbbe8156f6a9ce..6675b83c9f15d0341dcf169ec3ac20f401c5d10b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -266,7 +266,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -267,7 +267,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private String serverId;
public MinecraftServer.ReloadableResources resources;
private final StructureTemplateManager structureTemplateManager;
@@ -153,7 +153,7 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..d0d90a25a10bbecfffceee1992af88c6
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index 6b6c8ce49eda6806c8288d70848dd143ba2c4703..5d09d2c8bb45cc10b2a13100793249adc7b5a7e9 100644
index 126685fb266692082b432ed297a499149e921dfb..9d8f6025c420e651611da17e77a362c738228b72 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -14,7 +14,7 @@ import net.minecraft.server.ServerTickRateManager;
@@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 2 Jul 2025 23:36:25 +0800
Subject: [PATCH] Add config to enable datapack command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 0d5ed9602492c8393088954105e9a19032067b8b..e2fc15d84fafde6847ecead23c55169449275e1b 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -192,7 +192,9 @@ public class Commands {
if(me.earthme.luminol.config.modules.experiment.CommandDataConfig.enabled) {
DataCommands.register(this.dispatcher); // Folia - region threading - TODO
}
- //DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.datapack) {
+ DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
+ }
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
DefaultGameModeCommands.register(this.dispatcher);
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 6675b83c9f15d0341dcf169ec3ac20f401c5d10b..e8c9e739de35313c0212bab97a202fa362fd0887 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2349,6 +2349,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"));
@@ -3,9 +3,12 @@ From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 11 Apr 2025 16:53:57 +0800
Subject: [PATCH] Add config to revert raid changes
Co-authored by: huanli233 <392352840@qq.com>
Some of changes is a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/b5793e809b6346e16b7ea218496806a312562e27/leaves-server/minecraft-patches/features/0106-Revert-raid-changes.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java
index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc353bdb99b 100644
index 80f17f33f670018240c854df589cf90cdeab6e70..985f27d249810bf133a520d937b7006e57f553ec 100644
--- a/net/minecraft/world/effect/BadOmenMobEffect.java
+++ b/net/minecraft/world/effect/BadOmenMobEffect.java
@@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect {
@@ -13,7 +16,7 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc3
&& level.getDifficulty() != Difficulty.PEACEFUL
&& level.isVillage(serverPlayer.blockPosition())) {
+ // Leaves start - Revert raid changes
+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.trigger) {
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.trigger) {
+ return level.getRaids().createOrExtendRaid(serverPlayer, serverPlayer.blockPosition()) == null;
+ }
+ // Leaves end - Revert raid changes
@@ -21,7 +24,7 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc3
if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) {
serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier));
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e032e6add8 100644
index 1910bff3f08147bfd63703097e30b9f88c84e337..26f4d7359f638a11ea2d768d18091e261d6b1791 100644
--- a/net/minecraft/world/entity/raid/Raid.java
+++ b/net/minecraft/world/entity/raid/Raid.java
@@ -340,7 +340,20 @@ public class Raid {
@@ -30,7 +33,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0
if (flag1) {
- this.waveSpawnPos = this.getValidSpawnPos(level);
+ // Luminol Start - Raid revert
+ if (!me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
+ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
+ this.waveSpawnPos = this.getValidSpawnPos(level);
+ } else {
+ int n4 = 0;
@@ -53,7 +56,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0
- BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
+ // Luminol Start - Raid revert
+ BlockPos blockPos;
+ if (!me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
+ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) {
+ blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20));
+ } else {
+ blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(level, i, 20);
@@ -67,7 +70,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0
}
- if (i > 5) {
+ if (i > (me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert ? 3 : 5)) { // Luminol - Raid revert
+ if (i > (fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert ? 3 : 5)) { // Luminol - Raid revert
org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit
this.stop();
break;
@@ -94,7 +97,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0
int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f);
int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3);
- if (Mth.abs(height - this.center.getY()) <= 96) {
+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.heightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - Disable height check
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.heightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - Disable height check
mutableBlockPos.set(i2, height, i3);
if (!level.isVillage(mutableBlockPos) || i <= 7) {
int i4 = 10;
@@ -126,16 +129,16 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0
// Folia start - make raids thread-safe
if (!this.ownsRaid(level)) {
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e022e52843 100644
index 3e30989c99cd11c8c94d6fd194d2969e3a7efda6..510514e363f4816a6e286fb9b5488153e03c9e55 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -127,6 +127,41 @@ public abstract class Raider extends PatrollingMonster {
@@ -128,6 +128,41 @@ public abstract class Raider extends PatrollingMonster {
currentRaid.removeFromRaid(serverLevel, this, false);
}
+
+ // Leaves start - Revert raid changes
+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.effect && !this.hasRaid()) {
+ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.effect && !this.hasRaid()) {
+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
+ net.minecraft.world.entity.player.Player entityhuman = null;
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
@@ -159,7 +162,7 @@ index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e0
+ }
+
+ i = net.minecraft.util.Mth.clamp(i, 0, 4);
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
+
+ if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
@@ -171,17 +174,17 @@ index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e0
}
super.die(cause);
@@ -155,7 +190,7 @@ public abstract class Raider extends PatrollingMonster {
@@ -156,7 +191,7 @@ public abstract class Raider extends PatrollingMonster {
}
public boolean hasRaid() {
- return this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null);
+ return !me.earthme.lophine.config.modules.misc.RaidChangesConfig.selfCheck && (this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null)); // Leaves - Disable raid self check
+ return !fun.bm.lophine.config.modules.misc.RaidChangesConfig.selfCheck && (this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null)); // Leaves - Disable raid self check
}
public boolean hasActiveRaid() {
diff --git a/net/minecraft/world/item/component/OminousBottleAmplifier.java b/net/minecraft/world/item/component/OminousBottleAmplifier.java
index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73db6943b04 100644
index 33907bb190ffa22ccf9ea424b1e536297878711a..2fca459f2c888079322f6b957bbee3ac0e33c4bc 100644
--- a/net/minecraft/world/item/component/OminousBottleAmplifier.java
+++ b/net/minecraft/world/item/component/OminousBottleAmplifier.java
@@ -29,7 +29,7 @@ public record OminousBottleAmplifier(int value) implements ConsumableListener, T
@@ -189,7 +192,7 @@ index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73d
@Override
public void onConsume(Level level, LivingEntity entity, ItemStack stack, Consumable consumable) {
- entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below
+ entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below // Luminol - Raid effect infinite
+ entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below // Luminol - Raid effect infinite
}
// Paper start - properly resend entities - collect packets for bundle
@@ -198,7 +201,7 @@ index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73d
@Override
public void addToTooltip(Item.TooltipContext context, Consumer<Component> tooltipAdder, TooltipFlag flag, DataComponentGetter componentGetter) {
- List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true));
+ List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Luminol - Raid effect infinite
+ List<MobEffectInstance> list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Luminol - Raid effect infinite
PotionContents.addPotionTooltip(list, tooltipAdder, 1.0F, context.tickRate());
}
}
@@ -5,15 +5,15 @@ Subject: [PATCH] Add config to enable Cross Region Damage trace
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b492f79102 100644
index 06e41bca6b964ca71ea7bca547b03cdb3610ba31..b7bc75648634aefc549a69631ab6e401eb902e7d 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1330,6 +1330,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1341,6 +1341,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
killCredit.awardKillScore(this, cause);
this.createWitherRose(killCredit);
+ // Luminol Start - Cross Region Damage trace
+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ final LivingEntity entitylivingnew = this.getKillCreditOrigin();
+ if (entitylivingnew != null) {
+ this.damageTransferToAsync(entitylivingnew, cause);
@@ -22,7 +22,7 @@ index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b4
}
this.level().broadcastEntityEvent(this, (byte)3);
@@ -1353,6 +1360,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1364,6 +1371,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
}
// Leaves end - exp fix
@@ -48,10 +48,10 @@ index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b4
AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0);
this.level()
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a20ea8a351 100644
index d55a6989fd68f0bcf7bd05e9420fda1115afa6c0..5369a6597e48ed9f0d8f7f0b9685ce4950df4fe5 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -1191,6 +1191,29 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1216,6 +1216,29 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
}
@@ -59,7 +59,7 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2
+ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent, boolean async) {
+ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
+ return addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true);
+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ postToEntityThreadAddEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true);
+ return true;
+ }
@@ -81,12 +81,12 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2
public boolean canBeAffected(MobEffectInstance effectInstance) {
if (this.getType().is(EntityTypeTags.IMMUNE_TO_INFESTED)) {
return !effectInstance.is(MobEffects.INFESTED);
@@ -1916,6 +1939,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1948,6 +1971,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
final LivingEntity killer = this.getKillCredit();
if (killer != null) {
killer.awardKillScore(this, damageSource);
+ // Luminol Start - Cross Region Damage trace
+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ final LivingEntity killernew = this.getKillCreditOrigin();
+ if (killernew != null) {
+ this.damageTransferToAsync(killernew, damageSource);
@@ -95,7 +95,7 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2
}
}); // Paper end
this.postDeathDropItems(deathEvent); // Paper
@@ -1926,6 +1956,18 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -1958,6 +1988,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
return deathEvent; // Paper
}
@@ -114,7 +114,7 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2
protected void dropEquipment(ServerLevel level) {
}
protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
@@ -2524,6 +2566,18 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -2556,6 +2598,18 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}
}
@@ -134,16 +134,16 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2
return (float)this.getAttributeValue(Attributes.MAX_HEALTH);
}
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
index b2bb9b0ff94a7e463ebc4e59fe4378e022e52843..4b72db3350f2990b00076fffb9df811560db8207 100644
index 510514e363f4816a6e286fb9b5488153e03c9e55..4638af10539a316acae64fb26881c8e699c496e0 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -156,7 +156,13 @@ public abstract class Raider extends PatrollingMonster {
net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
@@ -157,7 +157,13 @@ public abstract class Raider extends PatrollingMonster {
net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true);
if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) {
- entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
+ if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ // Luminol start - Raid changes adapt DamageSource trace
+ // Luminol start - Raid changes adapt DamageSource trace
+ if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) {
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true, true);
+ } else {
+ entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable Raytracing tracker
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index ee53f78396f4377d3e5c2998826f231208066ef6..607091ecbd4a7261f2c0d839ee4dd1d27fa2190a 100644
index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd16792507f 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1278,7 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -18,19 +18,19 @@ index ee53f78396f4377d3e5c2998826f231208066ef6..607091ecbd4a7261f2c0d839ee4dd1d2
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf58e93876 100644
index 894897a120123cb54f9dba898748724173c01f57..312c385780019bf483e79022bba3fe6e12ca3be7 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder;
import net.minecraft.world.scores.Team;
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
import org.jetbrains.annotations.Contract;
import org.slf4j.Logger;
-public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, DataComponentGetter, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity, dev.tr7zw.entityculling.versionless.access.Cullable { // Paper - rewrite chunk system // Paper - optimise entity tracker // Luminol - Ray tracing entity tracker
// CraftBukkit start
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
private static final int CURRENT_LEVEL = 2;
@@ -6106,4 +6106,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
@@ -6365,4 +6365,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -59,7 +59,7 @@ index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf
+
+ @Override
+ public boolean isCulled() {
+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled)
+ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled)
+ return false;
+ return this.culled;
+ }
@@ -71,17 +71,17 @@ index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf
+
+ @Override
+ public boolean isOutOfCamera() {
+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled)
+ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled)
+ return false;
+ return this.outOfCamera;
+ }
+
}
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 6b72ab233508e6df1eca34360ce76d102ee25a41..f39ee4605cc15102d6560afd1dad5f56dd53cf4e 100644
index 6f00ffa05d9597917574357e0069c9b056aa5ce2..5cc7a91e32f17d8d9585ae4844a4ed3b706e3273 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1109,6 +1109,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1119,6 +1119,9 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
public final int passengerTickTimerId;
public final int passengerInactiveTickTimerId;
// Folia end - profiler
@@ -92,53 +92,53 @@ index 6b72ab233508e6df1eca34360ce76d102ee25a41..f39ee4605cc15102d6560afd1dad5f56
public EntityType(
EntityType.EntityFactory<T> factory,
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..34c4c195519de03ec11897160b98c80353eb3d6c 100644
index 2842314c712449625e9275aff7707c916c3ea767..09b549fa9568aa1ae13b1b975db14a6268fdaa46 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -220,6 +220,25 @@ public abstract class Player extends LivingEntity {
@@ -229,6 +229,25 @@ public abstract class Player extends LivingEntity {
return (org.bukkit.craftbukkit.entity.CraftHumanEntity) super.getBukkitEntity();
}
// CraftBukkit end
+ // Luminol start - Raytracing entity tracker
+ public dev.tr7zw.entityculling.CullTask cullTask;
+ {
+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) {
+ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) {
+ this.cullTask = null;
+ }else {
+ final com.logisticscraft.occlusionculling.OcclusionCullingInstance culling = new com.logisticscraft.occlusionculling.OcclusionCullingInstance(
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance,
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance,
+ new dev.tr7zw.entityculling.DefaultChunkDataProvider(this.level())
+ );
+
+ this.cullTask = new dev.tr7zw.entityculling.CullTask(
+ culling, this,
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit,
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit,
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs
+ );
+ }
+ }
+ // Luminol end
public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) {
public Player(Level level, GameProfile gameProfile) {
super(EntityType.PLAYER, level);
@@ -277,6 +296,26 @@ public abstract class Player extends LivingEntity {
@@ -287,6 +306,26 @@ public abstract class Player extends LivingEntity {
@Override
public void tick() {
+ // Luminol start - Ray tracing entity tracker
+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) {
+ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) {
+ if (this.cullTask != null) this.cullTask.signalStop();
+ this.cullTask = null;
+ }else {
+ final com.logisticscraft.occlusionculling.OcclusionCullingInstance culling = new com.logisticscraft.occlusionculling.OcclusionCullingInstance(
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance,
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance,
+ new dev.tr7zw.entityculling.DefaultChunkDataProvider(this.level())
+ );
+
+ this.cullTask = new dev.tr7zw.entityculling.CullTask(
+ culling, this,
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit,
+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit,
+ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs
+ );
+ }
+ if (this.cullTask != null) this.cullTask.setup();
@@ -148,7 +148,7 @@ index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..34c4c195519de03ec11897160b98c803
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
@@ -1415,6 +1454,7 @@ public abstract class Player extends LivingEntity {
@@ -1426,6 +1465,7 @@ public abstract class Player extends LivingEntity {
if (this.containerMenu != null && this.hasContainerOpen()) {
this.doCloseContainer();
}
@@ -0,0 +1,39 @@
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/item/trading/Merchant.java b/net/minecraft/world/item/trading/Merchant.java
index 6e2fa442ddcd4ef3c4fe789b9ebac9dd409c9de7..a876335e26daec9a9a3a2f00ee5cb23cfd913aa6 100644
--- a/net/minecraft/world/item/trading/Merchant.java
+++ b/net/minecraft/world/item/trading/Merchant.java
@@ -42,7 +42,14 @@ public interface Merchant {
new SimpleMenuProvider((containerId, inventory, player1) -> new MerchantMenu(containerId, inventory, this), displayName)
);
if (optionalInt.isPresent()) {
- MerchantOffers offers = this.getOffers();
+ // Lophine start - infinite trade
+ MerchantOffers offers = this.getOffers().copy();
+ if (fun.bm.lophine.config.modules.misc.VillagerConfig.villagerInfiniteTrade) {
+ for (MerchantOffer merchantOffer : offers) {
+ merchantOffer.maxUses = 16384;
+ }
+ }
+ // Lophine end - infinite trade
if (!offers.isEmpty()) {
player.sendMerchantOffers(optionalInt.getAsInt(), offers, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock());
}
diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java
index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..21ec77d5167cfdf05043ea474165148fb2b0c2d9 100644
--- a/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/net/minecraft/world/item/trading/MerchantOffer.java
@@ -196,7 +196,7 @@ public class MerchantOffer {
}
public boolean isOutOfStock() {
- return this.uses >= this.maxUses;
+ return (this.uses >= this.maxUses && !fun.bm.lophine.config.modules.misc.VillagerConfig.villagerInfiniteTrade); // Lophine - infinite trade
}
public void setToOutOfStock() {
@@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 18:19:00 +0800
Subject: [PATCH] Add config to enable unsafe waypoint bar
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index e2fc15d84fafde6847ecead23c55169449275e1b..b0a06cdfaa49237f372ecd131d47289160476b07 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -253,7 +253,11 @@ public class Commands {
TimeCommand.register(this.dispatcher);
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ // Lophine start - unsafe waypoint bar
+ if (fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) {
+ WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
+ }
+ // Lophine end - unsafe waypoint bar
WeatherCommand.register(this.dispatcher);
WorldBorderCommand.register(this.dispatcher);
if (JvmProfiler.INSTANCE.isAvailable()) {
diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java
index 0f8cacbb8fe55a60e2f0c98bf36c005b29f41a4b..36e9b027ce5213f8914728293633e78e9905c1b2 100644
--- a/net/minecraft/server/waypoints/ServerWaypointManager.java
+++ b/net/minecraft/server/waypoints/ServerWaypointManager.java
@@ -22,7 +22,14 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
@Override
public void trackWaypoint(WaypointTransmitter waypoint) {
- // Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ this.waypoints.add(waypoint);
+
+ for (ServerPlayer serverPlayer : this.players) {
+ this.createConnection(serverPlayer, waypoint);
+ }
+ // Lophine end - unsafe waypoint bar
}
@Override
@@ -50,14 +57,48 @@ public class ServerWaypointManager implements WaypointManager<WaypointTransmitte
public void addPlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ this.players.add(player);
+
+ for (WaypointTransmitter waypointTransmitter : this.waypoints) {
+ this.createConnection(player, waypointTransmitter);
+ }
+
+ if (player.isTransmittingWaypoint()) {
+ this.trackWaypoint((WaypointTransmitter)player);
+ }
+ // Lophine end - unsafe waypoint bar
}
public void updatePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ Map<WaypointTransmitter, WaypointTransmitter.Connection> map = this.connections.row(player);
+ SetView<WaypointTransmitter> set = Sets.difference(this.waypoints, map.keySet());
+
+ for (Entry<WaypointTransmitter, WaypointTransmitter.Connection> entry : ImmutableSet.copyOf(map.entrySet())) {
+ this.updateConnection(player, entry.getKey(), entry.getValue());
+ }
+
+ for (WaypointTransmitter waypointTransmitter : set) {
+ this.createConnection(player, waypointTransmitter);
+ }
+ // Lophine end - unsafe waypoint bar
}
public void removePlayer(ServerPlayer player) {
// Folia - region threading
+ // Lophine start - unsafe waypoint bar
+ if (!fun.bm.lophine.config.modules.experiment.WaypointConfig.forceEnableWaypointUnsafe) return;
+ this.connections.row(player).values().removeIf(connection -> {
+ connection.disconnect();
+ return true;
+ });
+ this.untrackWaypoint((WaypointTransmitter)player);
+ this.players.remove(player);
+ // Lophine end - unsafe waypoint bar
}
public void breakAllConnections() {
@@ -8,25 +8,25 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 001483b7098523f3645a95c81fcf0e38b551705e..3a83ba2fab530e9e64d53167d296c1f2ca1b9e4b 100644
index a24c332a8f9cb2ebc6f9926c6dabf1238238028d..58c2a6a3304e1bea25980b04046fe7c0017bc90d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1116,6 +1116,10 @@ public abstract class PlayerList {
@@ -1086,6 +1086,10 @@ public abstract class PlayerList {
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
} // Paper - Add sendOpLevel API
+
+ // Purpur start - Barrels and enderchests 6 rows
+ player.enderChestSlotCount = me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27;
+ player.enderChestSlotCount = fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27;
+ // Purpur end - Barrels and enderchests 6 rows
}
public boolean isWhiteListed(GameProfile profile) {
// Paper start - whitelist verify event / login event
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 34c4c195519de03ec11897160b98c80353eb3d6c..27e335e01d8f09f05a4fea5f15407dbe3a4555cb 100644
index 09b549fa9568aa1ae13b1b975db14a6268fdaa46..6c933c27ce155eb516a9ede96fb2c3bd19251bfa 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -210,6 +210,7 @@ public abstract class Player extends LivingEntity {
@@ -219,6 +219,7 @@ public abstract class Player extends LivingEntity {
private int currentImpulseContextResetGraceTime = 0;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
@@ -70,7 +70,7 @@ index 0fffa384f928ab84451331380968fb4650eafe26..d84a10396395939149da88bcb01be59e
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6);
}
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08ecef44f02 100644
index beb74bc8398de8b48f41af7daef14d624826310e..5dd6e89931d397b8afdb84024ed46b0d06dcf347 100644
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
@@ -25,11 +25,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
@@ -78,7 +78,7 @@ index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08e
public PlayerEnderChestContainer(Player owner) {
- super(27);
+ super(me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27);
+ super(fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27);
this.owner = owner;
// CraftBukkit end
}
@@ -94,7 +94,7 @@ index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08e
this.activeChest = enderChestBlockEntity;
}
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b15a4c40c 100644
index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..fe374f08b7829b846b2a1c2ac3ca500ca3e48684 100644
--- a/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
@@ -85,8 +85,14 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
@@ -103,7 +103,7 @@ index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b
new SimpleMenuProvider(
- (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
- )
+ (containerId, playerInventory, player1) -> switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ (containerId, playerInventory, player1) -> switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ case 6 -> ChestMenu.sixRows(containerId, playerInventory, enderChestInventory);
+ case 5 -> ChestMenu.fiveRows(containerId, playerInventory, enderChestInventory);
+ case 4 -> ChestMenu.fourRows(containerId, playerInventory, enderChestInventory);
@@ -115,7 +115,7 @@ index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
player.awardStat(Stats.OPEN_ENDERCHEST);
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff0695914e7b6e3 100644
index d679ab599dfd0bdbdc3ab5530d7fcd1c38baf7fa..6b4e2956222a0ca7f72f73032dc98878fbd257ee 100644
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -56,7 +56,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
@@ -124,7 +124,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
+ // Purpur start - Barrels and enderchests 6 rows
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
@@ -143,7 +143,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959
public int getContainerSize() {
- return 27;
+ // Purpur start - Barrels and enderchests 6 rows
+ return switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ return switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
@@ -161,7 +161,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959
protected AbstractContainerMenu createMenu(int id, Inventory player) {
- return ChestMenu.threeRows(id, player, this);
+ // Purpur start - Barrels and enderchests 6 rows
+ return switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ return switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> ChestMenu.sixRows(id, player, this);
+ case 5 -> ChestMenu.fiveRows(id, player, this);
+ case 4 -> ChestMenu.fourRows(id, player, this);
@@ -1,174 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 14 Jun 2025 05:32:51 +0800
Subject: [PATCH] Better ShulkerBox
You can open shulker box with shift & right click
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 1764875b9024569671bf2be537afb8b492f79102..0ae350d7e4b63abad1666c84df6925c71b73a013 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -2351,6 +2351,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.containerMenu.removed(this);
this.inventoryMenu.transferState(this.containerMenu);
this.containerMenu = this.inventoryMenu;
+ this.shulkerOpen = false;
}
@Override
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
index 9fbd605df26d388c01d2ed9ca6a6138651e7f9a7..e8141cb25d6b9a433890e2cded188c2eb5bcf755 100644
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -470,6 +470,16 @@ public class Inventory implements Container, Nameable {
if (equipmentSlot != null) {
this.equipment.set(equipmentSlot, stack);
}
+
+ // Lophine start - better shulker box
+ if (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker && !this.player.pendingClosingShulker) {
+ boolean isMainHand = index == selected;
+ boolean isOffHand = index == 40;
+ if (isMainHand || isOffHand) {
+ me.earthme.lophine.utils.ShulkerBoxesUtil.inventoryCallBack(isMainHand, this.player);
+ }
+ }
+ // Lophine end - better shulker box
}
public ListTag save(ListTag listTag) {
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 27e335e01d8f09f05a4fea5f15407dbe3a4555cb..fbb9fee8223cc27125e4c0c94a7eb8acab5e9a13 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -211,6 +211,11 @@ public abstract class Player extends LivingEntity {
public boolean affectsSpawning = true; // Paper - Affects Spawning API
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
public int enderChestSlotCount = -1; // Purpur - Barrels and enderchests 6 rows
+ // Lophine start - better shulker box
+ public net.minecraft.world.InteractionHand shulkerHand;
+ public boolean pendingClosingShulker = false;
+ public boolean shulkerOpen = false;
+ // Lophine end - better shulker box
// CraftBukkit start
public boolean fauxSleeping;
@@ -595,11 +600,13 @@ public abstract class Player extends LivingEntity {
// Paper start - special close for unloaded inventory
public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
this.containerMenu = this.inventoryMenu;
+ this.shulkerOpen = false;
}
// Paper end - special close for unloaded inventory
public void closeContainer() {
this.containerMenu = this.inventoryMenu;
+ this.shulkerOpen = false;
}
protected void doCloseContainer() {
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index 6c5a01b065c7daa37219a8ab2a471d93e882e756..7b49b35e7a0b9872daceb620cf83b06ae61c3df9 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -697,7 +697,7 @@ public abstract class AbstractContainerMenu {
}
}
- private static void dropOrPlaceInInventory(Player player, ItemStack stack) {
+ public static void dropOrPlaceInInventory(Player player, ItemStack stack) { // Lophine - better shulker box
boolean flag = !player.isAlive(); //player.isRemoved() && player.getRemovalReason() != Entity.RemovalReason.CHANGED_DIMENSION; // Luminol - Fix uncorrected death check of folia
boolean flag1 = player instanceof ServerPlayer serverPlayer && serverPlayer.hasDisconnected();
if (flag || flag1) {
diff --git a/net/minecraft/world/inventory/ShulkerBoxMenu.java b/net/minecraft/world/inventory/ShulkerBoxMenu.java
index 903025c659e6a9423224fe65973696405c69ec6a..545fc46416932db922dc1476b983ac8b9b9f3c7b 100644
--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java
+++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java
@@ -53,7 +53,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu {
@Override
public boolean stillValid(Player player) {
- if (!this.checkReachable) return true; // CraftBukkit
+ if (!this.checkReachable || player.shulkerOpen) return true; // CraftBukkit // Lophine - better shulker box
return this.container.stillValid(player);
}
diff --git a/net/minecraft/world/item/Item.java b/net/minecraft/world/item/Item.java
index c52fb17d1e496a91223b7387cacb128c1865caee..86d43c4e81dfe9775400e09ae706d4e9cc640bd8 100644
--- a/net/minecraft/world/item/Item.java
+++ b/net/minecraft/world/item/Item.java
@@ -187,6 +187,13 @@ public class Item implements FeatureElement, ItemLike {
player.startUsingItem(hand);
return InteractionResult.CONSUME;
} else {
+ // Lophine start - better shulker box
+ if (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker
+ && player.isShiftKeyDown()
+ && me.earthme.lophine.utils.ShulkerBoxesUtil.checkIfCanOpen(itemInHand)) {
+ me.earthme.lophine.utils.ShulkerBoxesUtil.openShulkerBox(player, itemInHand, hand);
+ }
+ // Lophine end - better shulker box
return InteractionResult.PASS;
}
}
diff --git a/net/minecraft/world/item/component/ItemContainerContents.java b/net/minecraft/world/item/component/ItemContainerContents.java
index ecf794f94177fc7b6df483516d920719fbc6fa43..4fda59a4c17009a0009f3d3c13258f4ffcb300c3 100644
--- a/net/minecraft/world/item/component/ItemContainerContents.java
+++ b/net/minecraft/world/item/component/ItemContainerContents.java
@@ -33,7 +33,7 @@ public final class ItemContainerContents implements TooltipProvider {
public final NonNullList<ItemStack> items;
private final int hashCode;
- private ItemContainerContents(NonNullList<ItemStack> items) {
+ public ItemContainerContents(NonNullList<ItemStack> items) { // Lophine - better shulker box
if (items.size() > 256) {
throw new IllegalArgumentException("Got " + items.size() + " items, but maximum is 256");
} else {
diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
index 87ebdb6deb66662a38b3eec0dae27eaf859ecabb..e22114dbfbfd1619260a45929397c11c9356b8a0 100644
--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
@@ -46,6 +46,11 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
private ShulkerBoxBlockEntity.AnimationStatus animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED;
private float progress;
private float progressOld;
+ // Lophine start - better shulker box
+ public boolean haveRealBlock = true;
+ public Player createPlayer;
+ public ItemStack item;
+ // Lophine end - better shulker box
@Nullable
private final DyeColor color;
@@ -236,6 +241,15 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
return Component.translatable("container.shulkerBox");
}
+ // Lophine start - better shulker box
+ public void setItem(int index, ItemStack stack) {
+ super.setItem(index, stack);
+ if (!createPlayer.pendingClosingShulker && !haveRealBlock && me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker) {
+ me.earthme.lophine.utils.ShulkerBoxesUtil.shulkerBoxEntityCallBack(this);
+ }
+ }
+ // Lophine end - better shulker box
+
@Override
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
@@ -258,12 +272,12 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
}
@Override
- protected NonNullList<ItemStack> getItems() {
+ public NonNullList<ItemStack> getItems() { // Lophine - better shulker box
return this.itemStacks;
}
@Override
- protected void setItems(NonNullList<ItemStack> items) {
+ public void setItems(NonNullList<ItemStack> items) { // Lophine - better shulker box
this.itemStacks = items;
}
@@ -0,0 +1,153 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 23 Jul 2025 20:28:40 +0800
Subject: [PATCH] Redstone Shears Wrench
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/bfde470a867b74d177fe1b9a2a3ed5c49cd126c7/leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
index 8cf3e51e12f9cf98836657e722edb23943f9e866..dc3e33223ac7b11a969ef1a8e3fa73a9b8b44696 100644
--- a/net/minecraft/world/item/ShearsItem.java
+++ b/net/minecraft/world/item/ShearsItem.java
@@ -24,6 +24,30 @@ import net.minecraft.world.level.block.GrowingPlantHeadBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
+// Leaves start - shears wrench
+import net.minecraft.Util;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.level.block.ComparatorBlock;
+import net.minecraft.world.level.block.DispenserBlock;
+import net.minecraft.world.level.block.HopperBlock;
+import net.minecraft.world.level.block.ObserverBlock;
+import net.minecraft.world.level.block.RepeaterBlock;
+import net.minecraft.world.level.block.CrafterBlock;
+import net.minecraft.world.level.block.LeverBlock;
+import net.minecraft.world.level.block.CocoaBlock;
+import net.minecraft.world.level.block.TrapDoorBlock;
+import net.minecraft.world.level.block.FenceGateBlock;
+import net.minecraft.world.level.block.LightningRodBlock;
+import net.minecraft.world.level.block.RailBlock;
+import net.minecraft.world.level.block.BaseRailBlock;
+import net.minecraft.world.level.block.PoweredRailBlock;
+import net.minecraft.world.level.block.CalibratedSculkSensorBlock;
+import net.minecraft.world.level.block.piston.PistonBaseBlock;
+import net.minecraft.world.level.block.state.StateDefinition;
+import net.minecraft.world.level.block.state.properties.RailShape;
+import net.minecraft.world.level.block.state.properties.Property;
+// Leaves end - shears wrench
+
public class ShearsItem extends Item {
public ShearsItem(Item.Properties properties) {
super(properties);
@@ -80,7 +104,108 @@ public class ShearsItem extends Item {
return InteractionResult.SUCCESS;
} else {
+ // Leaves start - shears wrench
+ Block block = blockState.getBlock();
+ if (fun.bm.lophine.config.modules.misc.RedStoneConfig.shears &&
+ block instanceof ObserverBlock ||
+ block instanceof DispenserBlock ||
+ block instanceof PistonBaseBlock ||
+ block instanceof HopperBlock ||
+ block instanceof RepeaterBlock ||
+ block instanceof ComparatorBlock ||
+ block instanceof CrafterBlock ||
+ block instanceof LeverBlock ||
+ block instanceof CocoaBlock ||
+ block instanceof TrapDoorBlock ||
+ block instanceof FenceGateBlock ||
+ block instanceof LightningRodBlock ||
+ block instanceof CalibratedSculkSensorBlock ||
+ block instanceof BaseRailBlock
+ ) {
+ StateDefinition<Block, BlockState> blockstatelist = block.getStateDefinition();
+ Property<?> iblockstate;
+ if (block instanceof CrafterBlock) iblockstate = blockstatelist.getProperty("orientation");
+ else if (block instanceof BaseRailBlock) iblockstate = blockstatelist.getProperty("shape");
+ else iblockstate = blockstatelist.getProperty("facing");
+ Player player = context.getPlayer();
+
+ if (iblockstate == null || player == null) {
+ return InteractionResult.FAIL;
+ }
+
+ if (block instanceof BaseRailBlock) {
+ if (block instanceof RailBlock) {
+ if (blockState.getValue(RailBlock.SHAPE).isSlope()) {
+ return InteractionResult.FAIL;
+ }
+ } else {
+ if (getNameHelper(blockState, PoweredRailBlock.POWERED).equals("true")) {
+ return InteractionResult.FAIL;
+ }
+ if (blockState.getValue(PoweredRailBlock.SHAPE).isSlope()) {
+ return InteractionResult.FAIL;
+ }
+ }
+ }
+
+ if (block instanceof PistonBaseBlock) {
+ if (getNameHelper(blockState, PistonBaseBlock.EXTENDED).equals("true")) {
+ return InteractionResult.FAIL;
+ }
+ }
+
+ if (block instanceof RepeaterBlock || block instanceof ComparatorBlock) {
+ if (getNameHelper(blockState, ComparatorBlock.POWERED).equals("true")) {
+ return InteractionResult.FAIL;
+ }
+ if (block instanceof RepeaterBlock) {
+ if (getNameHelper(blockState, RepeaterBlock.LOCKED).equals("true")) {
+ return InteractionResult.FAIL;
+ }
+ }
+ }
+
+ if (block instanceof CrafterBlock) {
+ if (getNameHelper(blockState, CrafterBlock.CRAFTING).equals("true")) {
+ return InteractionResult.FAIL;
+ }
+ }
+
+ BlockState iblockdata1 = ShearsItem.cycleState(blockState, iblockstate, player.isSecondaryUseActive());
+ level.setBlock(clickedPos, iblockdata1, 18);
+ ShearsItem.message(player, Component.translatable("item.minecraft.debug_stick.update", iblockstate.getName(), ShearsItem.getNameHelper(iblockdata1, iblockstate)));
+ return InteractionResult.CONSUME;
+ }
+ // Leaves end - shears wrench
+
return super.useOn(context);
}
}
+
+ // Leaves start - shears wrench
+ private static <T extends Comparable<T>> BlockState cycleState(BlockState state, Property<T> property, boolean inverse) {
+ List<T> possibleValues = property.getPossibleValues();
+ if (possibleValues.getFirst() instanceof RailShape) {
+ boolean isRailBlock = state.getBlock() instanceof RailBlock;
+ possibleValues = possibleValues.stream().filter(possibleValue -> {
+ RailShape shape = (RailShape) possibleValue;
+ if (isRailBlock) return !shape.isSlope();
+ return !shape.isSlope() && shape != RailShape.NORTH_EAST && shape != RailShape.NORTH_WEST && shape != RailShape.SOUTH_EAST && shape != RailShape.SOUTH_WEST;
+ }).toList();
+ }
+ return state.setValue(property, ShearsItem.getRelative(possibleValues, state.getValue(property), inverse)); // CraftBukkit - decompile error
+ }
+
+ private static <T> T getRelative(Iterable<T> elements, T current, boolean inverse) {
+ return inverse ? Util.findPreviousInIterable(elements, current) : Util.findNextInIterable(elements, current);
+ }
+
+ private static void message(Player player, Component message) {
+ ((ServerPlayer) player).sendSystemMessage(message, true);
+ }
+
+ private static <T extends Comparable<T>> String getNameHelper(BlockState state, Property<T> property) {
+ return property.getName(state.getValue(property));
+ }
+ // Leaves end - shears wrench
}
@@ -8,7 +8,7 @@ Some of changes is a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/9
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java
index 643797124fe5a4489d0b7419b7e600c04f283ef2..3c0d01d444210029b6380417c6ee0e6408f89c18 100644
index 643797124fe5a4489d0b7419b7e600c04f283ef2..3b4d97c76db9c742072c92dd7c8b39553c62a1f1 100644
--- a/net/minecraft/commands/arguments/item/ItemInput.java
+++ b/net/minecraft/commands/arguments/item/ItemInput.java
@@ -39,8 +39,9 @@ public class ItemInput {
@@ -17,74 +17,74 @@ index 643797124fe5a4489d0b7419b7e600c04f283ef2..3c0d01d444210029b6380417c6ee0e64
itemStack.applyComponents(this.components);
- if (allowOversizedStacks && count > itemStack.getMaxStackSize()) {
- throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize());
+ int maxCount = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
+ int maxCount = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
+ if (allowOversizedStacks && count > maxCount) { // Lophine - Stackable ShulkerBoxes
+ throw ERROR_STACK_TOO_BIG.create(this.getItemName(), maxCount); // Lophine - Stackable ShulkerBoxes
} else {
return itemStack;
}
diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java
index c1c0dea9f5ac3101c2f12714c8dd460457d45cb7..f94fc39297caebd0cb14d7b71c865f13b5c3b17c 100644
index 5a1c21b05545a03fbb00cf734605049870d3eecb..2ade5ce23cdab08b1746e2cbe99bfe1d3da42f02 100644
--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -52,7 +52,7 @@ public class GiveCommand {
@@ -55,7 +55,7 @@ public class GiveCommand {
private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
ItemStack itemStack = item.createItemStack(1, false);
final Component displayName = itemStack.getDisplayName(); // Paper - get display name early
- int maxStackSize = itemStack.getMaxStackSize();
+ int maxStackSize = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
+ int maxStackSize = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
int i = maxStackSize * 100;
if (count > i) {
source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName()));
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c61a70377 100644
index 68f0023c4234585a8385a830ed410883c8bd1549..1aed2578bb5f4e605fe68d1cfe4dce6a4cf5a1f7 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3056,7 +3056,7 @@ public class ServerGamePacketListenerImpl
@@ -3076,7 +3076,7 @@ public class ServerGamePacketListenerImpl
} else if (slot.mayPlace(cursor)) {
if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) {
int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1;
- toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount());
+ toPlace = Math.min(toPlace, me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(clickedItem) - clickedItem.getCount()); // Lophine - Stackable ShulkerBoxes
+ toPlace = Math.min(toPlace, fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(clickedItem) - clickedItem.getCount()); // Lophine - Stackable ShulkerBoxes
toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount());
if (toPlace == 1) {
action = InventoryAction.PLACE_ONE;
@@ -3092,7 +3092,7 @@ public class ServerGamePacketListenerImpl
@@ -3112,7 +3112,7 @@ public class ServerGamePacketListenerImpl
}
} else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) {
if (clickedItem.getCount() >= 0) {
- if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) {
+ if (clickedItem.getCount() + cursor.getCount() <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(cursor)) { // Lophine - Stackable ShulkerBoxes
+ if (clickedItem.getCount() + cursor.getCount() <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(cursor)) { // Lophine - Stackable ShulkerBoxes
// As of 1.5, this is result slots only
action = InventoryAction.PICKUP_ALL;
}
@@ -3351,6 +3351,7 @@ public class ServerGamePacketListenerImpl
@@ -3323,6 +3323,7 @@ public class ServerGamePacketListenerImpl
this.player.containerMenu.broadcastFullState();
} else {
this.player.containerMenu.broadcastChanges();
+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes
+ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes
}
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
}
@@ -3463,7 +3464,7 @@ public class ServerGamePacketListenerImpl
@@ -3433,7 +3434,7 @@ public class ServerGamePacketListenerImpl
}
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
- boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
+ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
+ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes
if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot
// CraftBukkit start - Call click event
org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView();
@@ -3505,6 +3506,7 @@ public class ServerGamePacketListenerImpl
@@ -3475,6 +3476,7 @@ public class ServerGamePacketListenerImpl
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
this.player.inventoryMenu.broadcastChanges();
+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes
+ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes
if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
} else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) {
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
index b382665cc125b8b5c0938e5e55984e4bf91d37ff..8ff16372df12f07e47d81fe45ad7270bb5c2b052 100644
index b382665cc125b8b5c0938e5e55984e4bf91d37ff..5d8bd05f966cf9befe8b8f3359b2fa4ce2428e98 100644
--- a/net/minecraft/world/Container.java
+++ b/net/minecraft/world/Container.java
@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable<ItemStack> {
@@ -93,7 +93,7 @@ index b382665cc125b8b5c0938e5e55984e4bf91d37ff..8ff16372df12f07e47d81fe45ad7270b
+ // Leaves start - stackable shulker boxes
+ default int getMaxStackLeaves(ItemStack stack) {
+ return Math.min(this.getMaxStackSize(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack));
+ return Math.min(this.getMaxStackSize(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack));
+ }
+ // Leaves end - stackable shulker boxes
+
@@ -101,7 +101,7 @@ index b382665cc125b8b5c0938e5e55984e4bf91d37ff..8ff16372df12f07e47d81fe45ad7270b
boolean stillValid(Player player);
diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java
index 133e042371bcf84f1935903ec57d204e3b7abd84..201599988e20219b6a99bf1594ad6c0c19e09038 100644
index d907e24d563e27acab2f2bf9711b1755ea9afd19..6189cb7c1745a242b610e89c859cc849f16cc9e3 100644
--- a/net/minecraft/world/SimpleContainer.java
+++ b/net/minecraft/world/SimpleContainer.java
@@ -211,7 +211,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
@@ -123,28 +123,28 @@ index 133e042371bcf84f1935903ec57d204e3b7abd84..201599988e20219b6a99bf1594ad6c0c
if (min > 0) {
other.grow(min);
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8be93ad0d7 100644
index b745eb5d9c68547335247910ff2ae8d5fb36349c..6d8675b918f92dc3ce85825edf2b33469950ef9d 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -281,10 +281,45 @@ public class ItemEntity extends Entity implements TraceableEntity {
@@ -279,10 +279,45 @@ public class ItemEntity extends Entity implements TraceableEntity {
private boolean isMergable() {
ItemStack item = this.getItem();
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item); // Paper - Alternative item-despawn-rate // Lophine - Stackable ShulkerBoxes
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item); // Paper - Alternative item-despawn-rate // Lophine - Stackable ShulkerBoxes
+ }
+
+ // Lophine start - Stackable ShulkerBoxes
+ private boolean tryMergeShulkerBox(ItemEntity ote) {
+ ItemStack sf = this.getItem();
+ ItemStack ot = ote.getItem();
+ if (!me.earthme.lophine.utils.ShulkerBoxesUtil.checkShulkerBox(sf)) return false;
+ if (!fun.bm.lophine.utils.ShulkerBoxesUtil.checkShulkerBox(sf)) return false;
+ if (sf.getItem().equals(ot.getItem())
+ && me.earthme.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(sf)
+ && me.earthme.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(ot)
+ && fun.bm.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(sf)
+ && fun.bm.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(ot)
+ && Objects.equals(sf.getComponents(), ot.getComponents()) // empty block entity tags are cleaned up when spawning
+ && sf.getCount() != me.earthme.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe()) {
+ int count = Math.min(ot.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe() - sf.getCount());
+ && sf.getCount() != fun.bm.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe()) {
+ int count = Math.min(ot.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe() - sf.getCount());
+ sf.grow(count);
+ this.setItem(sf);
+
@@ -165,7 +165,7 @@ index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8b
private void tryToMerge(ItemEntity itemEntity) {
+ // Lophine start - Stackable ShulkerBoxes
+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck()
+ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck()
+ && this.tryMergeShulkerBox(itemEntity)) {
+ return;
+ }
@@ -174,39 +174,39 @@ index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8b
ItemStack item1 = itemEntity.getItem();
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a6138651e7f9a7 100644
index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..53210a7d32241c47c2b1cd698b515726f0a1fd0d 100644
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -149,8 +149,8 @@ public class Inventory implements Container, Nameable {
@@ -166,8 +166,8 @@ public class Inventory implements Container, Nameable {
private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) {
return !destination.isEmpty()
- && destination.isStackable()
- && destination.getCount() < this.getMaxStackSize(destination)
+ && me.earthme.lophine.utils.ShulkerBoxesUtil.isStackable(destination) // Lophine - Stackable ShulkerBoxes
+ && destination.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(destination) // Lophine - Stackable ShulkerBoxes
+ && fun.bm.lophine.utils.ShulkerBoxesUtil.isStackable(destination) // Lophine - Stackable ShulkerBoxes
+ && destination.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(destination) // Lophine - Stackable ShulkerBoxes
&& ItemStack.isSameItemSameComponents(destination, origin); // Paper - check if itemstack is stackable first
}
@@ -164,7 +164,7 @@ public class Inventory implements Container, Nameable {
@@ -181,7 +181,7 @@ public class Inventory implements Container, Nameable {
}
if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) {
- remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount();
+ remains -= (me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) < this.getMaxStackSize() ? me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Lophine - Stackable ShulkerBoxes
+ remains -= (fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) < this.getMaxStackSize() ? fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Lophine - Stackable ShulkerBoxes
}
if (remains <= 0) {
return itemStack.getCount();
@@ -173,7 +173,7 @@ public class Inventory implements Container, Nameable {
@@ -190,7 +190,7 @@ public class Inventory implements Container, Nameable {
ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND);
if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) {
- remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount();
+ remains -= (me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) < this.getMaxStackSize() ? me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Lophine - Stackable ShulkerBoxes
+ remains -= (fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) < this.getMaxStackSize() ? fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Lophine - Stackable ShulkerBoxes
}
if (remains <= 0) {
return itemStack.getCount();
@@ -297,7 +297,7 @@ public class Inventory implements Container, Nameable {
@@ -314,7 +314,7 @@ public class Inventory implements Container, Nameable {
this.setItem(slot, item);
}
@@ -215,17 +215,17 @@ index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a61386
int min = Math.min(count, i);
if (min == 0) {
return count;
@@ -403,7 +403,7 @@ public class Inventory implements Container, Nameable {
@@ -420,7 +420,7 @@ public class Inventory implements Container, Nameable {
break;
}
- int i = stack.getMaxStackSize() - this.getItem(slotWithRemainingSpace).getCount();
+ int i = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Lophine - Stackable ShulkerBoxes
+ int i = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Lophine - Stackable ShulkerBoxes
if (this.add(slotWithRemainingSpace, stack.split(i)) && sendPacket && this.player instanceof ServerPlayer serverPlayer) {
serverPlayer.connection.send(this.createInventoryUpdatePacket(slotWithRemainingSpace));
}
diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java
index 83ccde54c625d40dc595e000c533f60aa929bd5a..16e9ac7449761c1427a528be60e964ef737ce897 100644
index 83ccde54c625d40dc595e000c533f60aa929bd5a..3206b599481eeab29c58bc1ca9cac6935da9963a 100644
--- a/net/minecraft/world/entity/player/StackedItemContents.java
+++ b/net/minecraft/world/entity/player/StackedItemContents.java
@@ -23,7 +23,7 @@ public class StackedItemContents {
@@ -233,12 +233,12 @@ index 83ccde54c625d40dc595e000c533f60aa929bd5a..16e9ac7449761c1427a528be60e964ef
public void accountStack(ItemStack stack) {
- this.accountStack(stack, stack.getMaxStackSize());
+ this.accountStack(stack, me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable Shulker Boxes
+ this.accountStack(stack, fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable Shulker Boxes
}
public void accountStack(ItemStack stack, int maxStackSize) {
diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java
index feebd1610ebd3c26a337259c14f5c774dc72b937..7df6ff842e41763aec2d88d1f8a5f7503932d905 100644
index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..d042b3729a615bdabeb08f559ac895a731856545 100644
--- a/net/minecraft/world/entity/vehicle/ContainerEntity.java
+++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java
@@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider {
@@ -251,10 +251,10 @@ index feebd1610ebd3c26a337259c14f5c774dc72b937..7df6ff842e41763aec2d88d1f8a5f750
default SlotAccess getChestVehicleSlot(final int index) {
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93e882e756 100644
index 9b6cd35e4dfa894069238a1365db16050aa5542b..a928c2e50e43245542a8bc8e307acf27259bbf74 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -234,6 +234,14 @@ public abstract class AbstractContainerMenu {
@@ -258,6 +258,14 @@ public abstract class AbstractContainerMenu {
return list;
}
@@ -269,39 +269,39 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93
public void broadcastChanges() {
for (int i = 0; i < this.slots.size(); i++) {
ItemStack item = this.slots.get(i).getItem();
@@ -427,7 +435,7 @@ public abstract class AbstractContainerMenu {
@@ -451,7 +459,7 @@ public abstract class AbstractContainerMenu {
&& (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size())
&& this.canDragTo(slot1)) {
int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0;
- int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack));
+ int min = Math.min(me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Lophine - Stackable ShulkerBoxes
+ int min = Math.min(fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Lophine - Stackable ShulkerBoxes
int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min);
count -= min1 - i2;
// slot1.setByPlayer(itemStack.copyWithCount(min1));
@@ -541,7 +549,7 @@ public abstract class AbstractContainerMenu {
@@ -563,7 +571,7 @@ public abstract class AbstractContainerMenu {
slot.setByPlayer(carried2);
}
} else if (ItemStack.isSameItemSameComponents(carried, carried2)) {
- Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player);
+ Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(carried2) - carried2.getCount(), player); // Lophine - Stackable ShulkerBoxes
+ Optional<ItemStack> optional1 = slot.tryRemove(carried.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(carried2) - carried2.getCount(), player); // Lophine - Stackable ShulkerBoxes
optional1.ifPresent(itemStack2 -> {
carried2.grow(itemStack2.getCount());
slot.onTake(player, itemStack2);
@@ -603,7 +611,7 @@ public abstract class AbstractContainerMenu {
@@ -625,7 +633,7 @@ public abstract class AbstractContainerMenu {
Slot slot2 = this.slots.get(slotId);
if (slot2.hasItem()) {
ItemStack itemStack = slot2.getItem();
- this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize()));
+ this.setCarried(itemStack.copyWithCount(me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack))); // Lophine - Stackable ShulkerBoxes
+ this.setCarried(itemStack.copyWithCount(fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack))); // Lophine - Stackable ShulkerBoxes
}
} else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) {
Slot slot2 = this.slots.get(slotId);
@@ -634,15 +642,15 @@ public abstract class AbstractContainerMenu {
@@ -656,15 +664,15 @@ public abstract class AbstractContainerMenu {
int maxStackSize = button == 0 ? 1 : -1;
for (int i3 = 0; i3 < 2; i3++) {
- for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < itemStack.getMaxStackSize(); i4 += maxStackSize) {
+ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); i4 += maxStackSize) { // Lophine - Stackable ShulkerBoxes
+ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); i4 += maxStackSize) { // Lophine - Stackable ShulkerBoxes
Slot slot3 = this.slots.get(i4);
if (slot3.hasItem()
&& canItemQuickReplace(slot3, itemStack, true)
@@ -310,39 +310,39 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93
ItemStack item1 = slot3.getItem();
- if (i3 != 0 || item1.getCount() != item1.getMaxStackSize()) {
- ItemStack itemStack1 = slot3.safeTake(item1.getCount(), itemStack.getMaxStackSize() - itemStack.getCount(), player);
+ if (i3 != 0 || item1.getCount() != me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item1)) { // Lophine - stackable shulker boxes
+ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack) - itemStack.getCount(), player); // Lophine - stackable shulker boxes
+ if (i3 != 0 || item1.getCount() != fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item1)) { // Lophine - stackable shulker boxes
+ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack) - itemStack.getCount(), player); // Lophine - stackable shulker boxes
itemStack.grow(itemStack1.getCount());
}
}
@@ -744,7 +752,7 @@ public abstract class AbstractContainerMenu {
@@ -766,7 +774,7 @@ public abstract class AbstractContainerMenu {
i = endIndex - 1;
}
- if (stack.isStackable()) {
+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.isStackable(stack)) { // Lophine - Stackable ShulkerBoxes
+ if (fun.bm.lophine.utils.ShulkerBoxesUtil.isStackable(stack)) { // Lophine - Stackable ShulkerBoxes
while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) {
Slot slot = this.slots.get(i);
ItemStack item = slot.getItem();
@@ -845,7 +853,7 @@ public abstract class AbstractContainerMenu {
@@ -867,7 +875,7 @@ public abstract class AbstractContainerMenu {
public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) {
boolean flag = slot == null || !slot.hasItem();
return !flag && ItemStack.isSameItemSameComponents(stack, slot.getItem())
- ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize()
+ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) // Lophine - Stackable ShulkerBoxes
+ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) // Lophine - Stackable ShulkerBoxes
: flag;
}
@@ -853,7 +861,7 @@ public abstract class AbstractContainerMenu {
@@ -875,7 +883,7 @@ public abstract class AbstractContainerMenu {
return switch (type) {
case 0 -> Mth.floor((float)stack.getCount() / slots.size());
case 1 -> 1;
- case 2 -> stack.getMaxStackSize();
+ case 2 -> me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack); // Lophine - Stackable ShulkerBoxes
+ case 2 -> fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack); // Lophine - Stackable ShulkerBoxes
default -> stack.getCount();
};
}
@@ -875,7 +883,7 @@ public abstract class AbstractContainerMenu {
@@ -897,7 +905,7 @@ public abstract class AbstractContainerMenu {
for (int i = 0; i < container.getContainerSize(); i++) {
ItemStack item = container.getItem(i);
if (!item.isEmpty()) {
@@ -365,7 +365,7 @@ index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..cf87267130c0aebd38206556261929d6
this.updateSellItem();
}
diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java
index 5ceb8964476b40db4511bec91ff13c4f522a1357..170353b8d1d330e54d9836e78ba2d41d023e0f51 100644
index 5ceb8964476b40db4511bec91ff13c4f522a1357..dd978d1590fb896775a240ed87e38d85744017d3 100644
--- a/net/minecraft/world/inventory/Slot.java
+++ b/net/minecraft/world/inventory/Slot.java
@@ -75,7 +75,7 @@ public class Slot {
@@ -373,15 +373,15 @@ index 5ceb8964476b40db4511bec91ff13c4f522a1357..170353b8d1d330e54d9836e78ba2d41d
public int getMaxStackSize(ItemStack stack) {
- return Math.min(this.getMaxStackSize(), stack.getMaxStackSize());
+ return Math.min(this.getMaxStackSize(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable ShulkerBoxes
+ return Math.min(this.getMaxStackSize(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable ShulkerBoxes
}
@Nullable
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f282c6bd2 100644
index 6154da1158756cff072d7e8cae10e20eafed1eec..687249e1ad1cb09edbe2939f1db2f90e146cd664 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -165,7 +165,7 @@ public final class ItemStack implements DataComponentHolder {
@@ -162,7 +162,7 @@ public final class ItemStack implements DataComponentHolder {
@Deprecated
@Nullable
private Item item;
@@ -390,24 +390,24 @@ index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f
@Nullable
private Entity entityRepresentation;
@@ -192,7 +192,8 @@ public final class ItemStack implements DataComponentHolder {
@@ -189,7 +189,8 @@ public final class ItemStack implements DataComponentHolder {
} else {
Holder<Item> holder = Item.STREAM_CODEC.decode(buffer);
DataComponentPatch dataComponentPatch = codec.decode(buffer);
- return new ItemStack(holder, varInt, dataComponentPatch);
+ ItemStack itemStack = new ItemStack(holder, varInt, dataComponentPatch);
+ return me.earthme.lophine.utils.ShulkerBoxesUtil.decodeMaxStackSize(itemStack);
+ return fun.bm.lophine.utils.ShulkerBoxesUtil.decodeMaxStackSize(itemStack);
}
}
@@ -201,13 +202,15 @@ public final class ItemStack implements DataComponentHolder {
@@ -198,13 +199,15 @@ public final class ItemStack implements DataComponentHolder {
if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
buffer.writeVarInt(0);
} else {
- buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count
- Item.STREAM_CODEC.encode(buffer, value.getItemHolder());
+ // Leaves start - stackable shulker boxes
+ final ItemStack itemStack = me.earthme.lophine.utils.ShulkerBoxesUtil.encodeMaxStackSize(value.copy());
+ final ItemStack itemStack = fun.bm.lophine.utils.ShulkerBoxesUtil.encodeMaxStackSize(value.copy());
+ buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count
+ Item.STREAM_CODEC.encode(buffer, itemStack.getItemHolder());
// Paper start - adventure; conditionally render translatable components
@@ -420,20 +420,20 @@ index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f
} finally {
net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
}
@@ -302,7 +305,7 @@ public final class ItemStack implements DataComponentHolder {
@@ -299,7 +302,7 @@ public final class ItemStack implements DataComponentHolder {
for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) {
int count = itemStack.getCount();
- int maxStackSize = itemStack.getMaxStackSize();
+ int maxStackSize = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Leaves - stackable shulker boxes
+ int maxStackSize = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Leaves - stackable shulker boxes
if (count > maxStackSize) {
return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize);
}
diff --git a/net/minecraft/world/level/block/AbstractCauldronBlock.java b/net/minecraft/world/level/block/AbstractCauldronBlock.java
index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..ee0315ff52914666e3e3cfc38f726512e3301986 100644
index 1a927b08f86c0585e62d8c4207954ab36d3316ee..e9899a03b15a2ca3dbd941775f14b041bbcfc85e 100644
--- a/net/minecraft/world/level/block/AbstractCauldronBlock.java
+++ b/net/minecraft/world/level/block/AbstractCauldronBlock.java
@@ -62,9 +62,27 @@ public abstract class AbstractCauldronBlock extends Block {
@@ -57,9 +57,27 @@ public abstract class AbstractCauldronBlock extends Block {
ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult
) {
CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem());
@@ -444,7 +444,7 @@ index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..ee0315ff52914666e3e3cfc38f726512
+ // Leaves start - stackable shulker boxes
+ private InteractionResult wrapInteractor(CauldronInteraction cauldronBehavior, BlockState blockState, Level world, BlockPos blockPos, Player playerEntity, InteractionHand hand, ItemStack itemStack, net.minecraft.core.Direction hitDirection) {
+ int count = -1;
+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck() && itemStack.getItem() instanceof net.minecraft.world.item.BlockItem bi &&
+ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck() && itemStack.getItem() instanceof net.minecraft.world.item.BlockItem bi &&
+ bi.getBlock() instanceof ShulkerBoxBlock) {
+ count = itemStack.getCount();
+ }
@@ -476,7 +476,7 @@ index 38b03c7b02bdfc579e5e126c12de3d878e26d188..33e24f2c3b63b2d3b55dfae2f2e55869
org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index c5b3b5e5f621f8db152aa190374ae0fe567d6828..0ca27b83151c3e7be3d681aa087fa72fb5bef0c3 100644
index 36a72a11d28f99bfe85868461925b778cc01478e..831900a4ed6ca335707289391a095af7717a01a4 100644
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -409,7 +409,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
@@ -489,10 +489,10 @@ index c5b3b5e5f621f8db152aa190374ae0fe567d6828..0ca27b83151c3e7be3d681aa087fa72f
this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
this.cookingTimer = 0;
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
index c63370fd458fb4f7190b79b1a8174fcc92d88f9c..4cca3fbbb93bb76d5d501dfad6997d909211809e 100644
index 5a094257a31f0500278a706a418e1697f8810ffb..1f132848ae284668c05d6ca17d5890fa341e14cd 100644
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -148,7 +148,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
@@ -145,7 +145,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
@Override
public void setItem(int slot, ItemStack stack) {
this.getItems().set(slot, stack);
@@ -502,7 +502,7 @@ index c63370fd458fb4f7190b79b1a8174fcc92d88f9c..4cca3fbbb93bb76d5d501dfad6997d90
}
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 6f5a47a3e9452f25b318e4a7a628e917da99c96f..52032c6bbc7e1c37a50d9b7334f1830896cb462d 100644
index 5de769e7bd56bb3355c3c711d46ce5e103ea4409..061501979195cf43c6da4d4b6cf6359251978bd3 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -123,7 +123,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 18 May 2025 23:48:59 +0800
Subject: [PATCH] Old nether portal collision
This patch should removed in 1.21.6 when mojang revert it.
diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java
index 421ea9c748159ac989900427a13abe9b244dc7aa..ecdecf0484137e0f98bf41d09e0dc7dc7715fd35 100644
--- a/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -65,7 +65,7 @@ public class NetherPortalBlock extends Block implements Portal {
@Override
protected VoxelShape getEntityInsideCollisionShape(BlockState state, BlockGetter level, BlockPos pos, Entity entity) {
- return state.getShape(level, pos);
+ return me.earthme.lophine.config.modules.misc.OldFeatureConfig.oldNetherPortalCollision ? Shapes.block() : state.getShape(level, pos); // Lophine - Old nether portal collision
}
@Override
@@ -5,10 +5,10 @@ Subject: [PATCH] Spawn invulnerable time
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 1764875b9024569671bf2be537afb8b492f79102..473f9de0908d3fb2cfb640ff7c6f7b78c1280721 100644
index b7bc75648634aefc549a69631ab6e401eb902e7d..0e2d575200f3ff3ec1600a0663152e3c37ea67b0 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -221,6 +221,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -232,6 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
private int lastSentFood = -99999999;
private boolean lastFoodSaturationZero = true;
public int lastSentExp = -99999999;
@@ -16,20 +16,20 @@ index 1764875b9024569671bf2be537afb8b492f79102..473f9de0908d3fb2cfb640ff7c6f7b78
private ChatVisiblity chatVisibility = ChatVisiblity.FULL;
public ParticleStatus particleStatus = ParticleStatus.ALL;
private boolean canChatColor = true;
@@ -923,6 +924,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -925,6 +926,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
+ if (me.earthme.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime && this.invulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
+ if (this.spawnInvulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time
if (this.invulnerableTime > 0) {
this.invulnerableTime--;
}
@@ -1420,6 +1422,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -1431,6 +1433,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else {
+ // Lophine start - spawn invulnerable time
+ if (me.earthme.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime) {
+ if (fun.bm.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime) {
+ if (this.spawnInvulnerableTime > 0 && !damageSource.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) {
+ return false;
+ }
@@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 7 Jul 2025 15:33:57 +0800
Subject: [PATCH] Old Explosion Damage Calculator
Co-authored by: MC_XiaoHei <xor7xiaohei@gmail.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e96b237749a960f297f211d439ffc9ea7fd2381/leaves-server/minecraft-patches/features/0134-Old-wet-tnt-explode-behavior.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index b3e897a4afee742b5055d652ad7047a660d8ea04..cf8869fac003c73024634078b2f7b36cddda640e 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -729,6 +729,7 @@ public class ServerExplosion implements Explosion {
public boolean shouldAffectBlocklikeEntities() {
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
boolean flag = this.source == null || this.source.getType() != EntityType.BREEZE_WIND_CHARGE && this.source.getType() != EntityType.WIND_CHARGE;
+ if (fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldExplosionDamageCalculator) flag = flag && (this.source == null || !this.source.isInWater()); // Leaves - Old MC TNT wet explosion no item damage
return _boolean ? flag : this.blockInteraction.shouldAffectBlocklikeEntities() && flag;
}
@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 18 Jun 2025 14:24:54 +0800
Subject: [PATCH] Old replaceable by mushrooms
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 93d722d437121e605cee0e168ac17ee9bef0610e..cb2a2fbd17157726b285665fdca0ab9663e0d1de 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -1111,7 +1111,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
if (worldData.captureTreeGeneration) { // Folia - region threading
// Paper start - Protect Bedrock and End Portal/Frames from being destroyed
BlockState type = getBlockState(pos);
- if (!type.isDestroyable()) return false;
+ if (!type.isDestroyable() && !(fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldReplaceableByMushrooms && flags == 3)) return false;
// Paper end - Protect Bedrock and End Portal/Frames from being destroyed
CraftBlockState blockstate = worldData.capturedBlockStates.get(pos); // Folia - region threading
if (blockstate == null) {
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 834e27ef2f7b342b074ff9e1e390e02f3ca1c399..f5765e3bbf9e735d6f959e1bf6ee1846ee11b4e9 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -770,6 +770,14 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.solidRender;
}
+ public boolean mushroomCheck(BlockState state) {
+ BlockState blockState = state.asState();
+ if (blockState.canOcclude()) {
+ return !Block.isShapeFullBlock(blockState.getOcclusionShape());
+ }
+ return true;
+ }
+
public final boolean canOcclude() { // Paper - Perf: Final for inlining
return this.canOcclude;
}
diff --git a/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java b/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java
index 3a37d66ab3c27c9abd60f35ef3bf3a93f8d7c3cd..2aad65d76cdd0800ac593a5bb3ce84ad1925eab0 100644
--- a/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java
+++ b/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java
@@ -26,7 +26,7 @@ public abstract class AbstractHugeMushroomFeature extends Feature<HugeMushroomFe
protected void placeMushroomBlock(LevelAccessor level, BlockPos.MutableBlockPos mutablePos, BlockState state) {
BlockState blockState = level.getBlockState(mutablePos);
- if (blockState.isAir() || blockState.is(BlockTags.REPLACEABLE_BY_MUSHROOMS)) {
+ if (blockState.isAir() || blockState.is(BlockTags.REPLACEABLE_BY_MUSHROOMS) || (fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldReplaceableByMushrooms && state.mushroomCheck(blockState))) { // Lophine - old replaceable by mushrooms
this.setBlock(level, mutablePos, state);
}
}
@@ -5,15 +5,15 @@ Subject: [PATCH] Old zombie reinforcement
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
index 4395947fc8c719864ac2afde5e6bbb53da5129c2..348e2b6020de8584b512ec849a5fba484380930e 100644
index 14d0758aca54d9a25e369dfa8c89c930f27946c9..6f1f26b7f759e56f843e674167470da943785728 100644
--- a/net/minecraft/world/entity/monster/Zombie.java
+++ b/net/minecraft/world/entity/monster/Zombie.java
@@ -342,7 +342,7 @@ public class Zombie extends Monster {
@@ -341,7 +341,7 @@ public class Zombie extends Monster {
int floor = Mth.floor(this.getX());
int floor1 = Mth.floor(this.getY());
int floor2 = Mth.floor(this.getZ());
- EntityType<? extends Zombie> type = this.getType();
+ EntityType<? extends Zombie> type = me.earthme.lophine.config.modules.misc.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement
+ EntityType<? extends Zombie> type = fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement
Zombie zombie = type.create(level, EntitySpawnReason.REINFORCEMENT);
if (zombie == null) {
return true;
@@ -5,14 +5,14 @@ Subject: [PATCH] I18n support
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index ba0cdba050cd3bf9231e15dd9543d34f37d9dae5..33e7cb15ceafdb246bb9cc1a43d9968d3f28ca6b 100644
index c6c6432c2efeb7b95c2894b188cd966321ae3186..1cd9af71ee66df5f277748c0a5a59a30bd57accc 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -172,6 +172,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
// Paper end - initialize global and world-defaults configuration
me.earthme.lophine.config.LophineConfig.loadConfigFiles(); //Luminol - load config file // Lophine - load config file
+ me.earthme.lophine.utils.ServerI18nUtil.init(); // Lophine - I18n support
me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // Luminol - load config file
+ fun.bm.lophine.utils.ServerI18nUtil.init(); // Lophine - I18n support
if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
if (this.convertOldUsers()) {
@@ -57,18 +57,19 @@ index 22125dbe1765f930fe10fe420be1c275ec553139..d5b070d1a3d84e228960dacd614e0f1a
final @Nullable Component history = this.getHistory();
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
index e3c5f4c31f084294a59830f3e764921433dd80d5..8b08a578102caf078efb15565ae3006c6eb50662 100644
index 4ada790812957657d580cb748077c4961987d0cb..3a539df860305e777e85ed6dc72b5effe76734b4 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
@@ -32,6 +32,7 @@ public record ServerBuildInfoImpl(
@@ -31,7 +31,7 @@ public record ServerBuildInfoImpl(
private static final String ATTRIBUTE_GIT_COMMIT = "Git-Commit";
private static final String BRAND_PAPER_NAME = "Paper";
private static final String BRAND_LUMINOL_NAME = "Luminol";
- private static final String BRAND_LUMINOL_NAME = "Luminol";
+ private static final String BRAND_LOPHINE_NAME = "Lophine";
private static final String BUILD_DEV = "DEV";
@@ -43,9 +44,9 @@ public record ServerBuildInfoImpl(
@@ -43,9 +43,9 @@ public record ServerBuildInfoImpl(
this(
getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID)
.map(Key::key)
@@ -77,10 +78,10 @@ index e3c5f4c31f084294a59830f3e764921433dd80d5..8b08a578102caf078efb15565ae3006c
getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME)
- .orElse(BRAND_LUMINOL_NAME), // Folia // Luminol
+ .orElse(BRAND_LOPHINE_NAME), // Folia // Luminol // Lophine
SharedConstants.getCurrentVersion().getId(),
SharedConstants.getCurrentVersion().getName(),
SharedConstants.getCurrentVersion().id(),
SharedConstants.getCurrentVersion().name(),
getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER)
@@ -62,7 +63,7 @@ public record ServerBuildInfoImpl(
@@ -62,7 +62,7 @@ public record ServerBuildInfoImpl(
@Override
public boolean isBrandCompatible(final @NotNull Key brandId) {
@@ -89,317 +90,8 @@ index e3c5f4c31f084294a59830f3e764921433dd80d5..8b08a578102caf078efb15565ae3006c
}
@Override
diff --git a/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
index fb63e2a3205ea9f7aaee0ff0f4dc0cc1a5268507..645f2f41de74f4461685c753dcd6cfc5dfa8b2ab 100644
--- a/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
+++ b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
@@ -13,11 +13,17 @@ import java.util.ArrayList;
import java.util.List;
public class LuminolConfigCommand extends Command {
- public LuminolConfigCommand() {
- super("luminolconfig");
- this.setPermission("luminol.commands.luminolconfig");
+ private LuminolConfig config;
+
+ public LuminolConfigCommand(String name) {
+ super(name + "config");
+ this.setPermission(name + ".commands." + name + "config");
this.setDescription("Manage config file");
- this.setUsage("/luminolconfig");
+ this.setUsage("/" + name + "config");
+ }
+
+ public void initConfig(LuminolConfig config) {
+ this.config = config;
}
public void wrongUse(CommandSender sender) {
@@ -38,7 +44,7 @@ public class LuminolConfigCommand extends Command {
result.add("reset");
result.add("reload");
} else if (args.length == 2 && (args[0].equals("query") || args[0].equals("set") || args[0].equals("reset"))) {
- result.addAll(LuminolConfig.completeConfigPath(args[1]));
+ result.addAll(config.completeConfigPath(args[1]));
}
return result;
}
@@ -59,7 +65,7 @@ public class LuminolConfigCommand extends Command {
switch (args[0]) {
case "reload" -> {
- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
Component
.text("Reloaded config file!")
.color(TextColor.color(0, 255, 0))
@@ -69,8 +75,8 @@ public class LuminolConfigCommand extends Command {
if (args.length == 2 || args.length > 3) {
wrongUse(sender);
return true;
- } else if (LuminolConfig.setConfig(args[1], args[2])) {
- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ } else if (config.setConfig(args[1], args[2])) {
+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
Component
.text("Set Config " + args[1] + " to " + args[2] + " successfully!")
.color(TextColor.color(0, 255, 0))
@@ -88,10 +94,10 @@ public class LuminolConfigCommand extends Command {
wrongUse(sender);
return true;
} else {
- LuminolConfig.resetConfig(args[1]);
- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ config.resetConfig(args[1]);
+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
Component
- .text("Reset Config " + args[1] + " to " + LuminolConfig.getConfig(args[1]) + " successfully!")
+ .text("Reset Config " + args[1] + " to " + config.getConfig(args[1]) + " successfully!")
.color(TextColor.color(0, 255, 0))
));
}
@@ -103,7 +109,7 @@ public class LuminolConfigCommand extends Command {
} else {
sender.sendMessage(
Component
- .text("Config " + args[1] + " is " + LuminolConfig.getConfig(args[1]) + "!")
+ .text("Config " + args[1] + " is " + config.getConfig(args[1]) + "!")
.color(TextColor.color(0, 255, 0))
);
}
diff --git a/src/main/java/me/earthme/luminol/config/LuminolConfig.java b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
index 57b1f606d2f4197e1f68d367bf63e04ce2fe1534..01f109fc02590d22a42676f35f23ae72ed08ac36 100644
--- a/src/main/java/me/earthme/luminol/config/LuminolConfig.java
+++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
@@ -29,22 +29,33 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class LuminolConfig {
- public static final Logger logger = LogManager.getLogger();
- private static final File baseConfigFolder = new File("luminol_config");
- private static final File baseConfigFile = new File(baseConfigFolder, "luminol_global_config.toml");
- private static final Set<IConfigModule> allInstanced = new HashSet<>();
- private static final Map<String, Object> stagedConfigMap = new HashMap<>();
- private static final Map<String, Object> defaultvalueMap = new HashMap<>();
- public static boolean alreadyInit = false;
- private static CommentedFileConfig configFileInstance;
-
- public static void setupLatch() {
- Bukkit.getCommandMap().register("luminolconfig", "luminol", new LuminolConfigCommand());
+ public final Logger logger = LogManager.getLogger();
+ private final File baseConfigFolder;
+ private final File baseConfigFile;
+ private final String name;
+ private final String pack;
+ private final Set<IConfigModule> allInstanced = new HashSet<>();
+ private final Map<String, Object> stagedConfigMap = new HashMap<>();
+ private final Map<String, Object> defaultvalueMap = new HashMap<>();
+ public boolean alreadyInit = false;
+ private CommentedFileConfig configFileInstance;
+
+ public LuminolConfig(@NotNull File base, @NotNull String name, @NotNull String pack) {
+ this.baseConfigFolder = base;
+ this.name = name;
+ this.pack = pack;
+ this.baseConfigFile = new File(base, name + "_global_config.toml");
+ }
+
+ public void setupLatch() {
+ LuminolConfigCommand command = new LuminolConfigCommand(name);
+ Bukkit.getCommandMap().register(name + "config", name, command);
+ command.initConfig(this);
alreadyInit = true;
}
- public static void reload() {
- RegionizedServer.ensureGlobalTickThread("Reload luminol config off global region thread!");
+ public void reload() {
+ RegionizedServer.ensureGlobalTickThread("Reload " + name + " config off global region thread!");
dropAllInstanced();
try {
@@ -56,8 +67,8 @@ public class LuminolConfig {
}
@Contract(" -> new")
- public static @NotNull CompletableFuture<Void> reloadAsync() {
- return CompletableFuture.runAsync(LuminolConfig::reload, task -> RegionizedServer.getInstance().addTask(() -> {
+ public @NotNull CompletableFuture<Void> reloadAsync() {
+ return CompletableFuture.runAsync(this::reload, task -> RegionizedServer.getInstance().addTask(() -> {
try {
task.run();
} catch (Exception e) {
@@ -66,17 +77,17 @@ public class LuminolConfig {
}));
}
- public static void dropAllInstanced() {
+ public void dropAllInstanced() {
allInstanced.clear();
}
- public static void finalizeLoadConfig() {
+ public void finalizeLoadConfig() {
for (IConfigModule module : allInstanced) {
module.onLoaded(configFileInstance);
}
}
- public static void preLoadConfig() throws IOException {
+ public void preLoadConfig() throws IOException {
baseConfigFolder.mkdirs();
if (!baseConfigFile.exists()) {
@@ -98,21 +109,21 @@ public class LuminolConfig {
saveConfigs();
}
- private static void loadAllModules() throws IllegalAccessException {
+ private void loadAllModules() throws IllegalAccessException {
for (IConfigModule instanced : allInstanced) {
loadForSingle(instanced);
}
}
- private static void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- for (Class<?> clazz : getClasses("me.earthme.luminol.config.modules")) {
+ private void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ for (Class<?> clazz : getClasses(pack)) {
if (IConfigModule.class.isAssignableFrom(clazz)) {
allInstanced.add((IConfigModule) clazz.getConstructor().newInstance());
}
}
}
- private static void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException {
+ private void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException {
final EnumConfigCategory category = singleConfigModule.getCategory();
Field[] fields = singleConfigModule.getClass().getDeclaredFields();
@@ -203,7 +214,7 @@ public class LuminolConfig {
}
}
- public static void removeConfig(String name, String[] keys) {
+ public void removeConfig(String name, String[] keys) {
configFileInstance.remove(name);
Object configAtPath = configFileInstance.get(String.join(".", keys));
if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) {
@@ -211,7 +222,7 @@ public class LuminolConfig {
}
}
- public static void removeConfig(String[] keys) {
+ public void removeConfig(String[] keys) {
configFileInstance.remove(String.join(".", keys));
Object configAtPath = configFileInstance.get(String.join(".", Arrays.copyOfRange(keys, 1, keys.length)));
if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) {
@@ -219,11 +230,11 @@ public class LuminolConfig {
}
}
- public static boolean setConfig(String[] keys, Object value) {
+ public boolean setConfig(String[] keys, Object value) {
return setConfig(String.join(".", keys), value);
}
- public static boolean setConfig(String key, Object value) {
+ public boolean setConfig(String key, Object value) {
if (configFileInstance.contains(key) && configFileInstance.get(key) != null) {
stagedConfigMap.put(key, value);
return true;
@@ -231,7 +242,7 @@ public class LuminolConfig {
return false;
}
- private static Object tryTransform(Class<?> targetType, Object value) {
+ private Object tryTransform(Class<?> targetType, Object value) {
if (!targetType.isAssignableFrom(value.getClass())) {
try {
if (targetType == Integer.class) {
@@ -255,27 +266,27 @@ public class LuminolConfig {
return value;
}
- public static void saveConfigs() {
+ public void saveConfigs() {
configFileInstance.save();
}
- public static void resetConfig(String[] keys) {
+ public void resetConfig(String[] keys) {
resetConfig(String.join(".", keys));
}
- public static void resetConfig(String key) {
+ public void resetConfig(String key) {
stagedConfigMap.put(key, null);
}
- public static String getConfig(String[] keys) {
+ public String getConfig(String[] keys) {
return getConfig(String.join(".", keys));
}
- public static String getConfig(String key) {
+ public String getConfig(String key) {
return configFileInstance.get(key).toString();
}
- public static List<String> completeConfigPath(String partialPath) {
+ public List<String> completeConfigPath(String partialPath) {
List<String> allPaths = getAllConfigPaths(partialPath);
List<String> result = new ArrayList<>();
@@ -295,13 +306,13 @@ public class LuminolConfig {
return result;
}
- private static List<String> getAllConfigPaths(String currentPath) {
+ private List<String> getAllConfigPaths(String currentPath) {
return defaultvalueMap.keySet().stream()
.filter(k -> k.startsWith(currentPath))
.toList();
}
- public static @NotNull Set<Class<?>> getClasses(String pack) {
+ public @NotNull Set<Class<?>> getClasses(String pack) {
Set<Class<?>> classes = new LinkedHashSet<>();
String packageDirName = pack.replace('.', '/');
Enumeration<URL> dirs;
@@ -332,7 +343,7 @@ public class LuminolConfig {
return classes;
}
- private static void findClassesInPackageByFile(String packageName, String packagePath, Set<Class<?>> classes) {
+ private void findClassesInPackageByFile(String packageName, String packagePath, Set<Class<?>> classes) {
File dir = new File(packagePath);
if (!dir.exists() || !dir.isDirectory()) {
@@ -356,7 +367,7 @@ public class LuminolConfig {
}
}
- private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, Set<Class<?>> classes) {
+ private void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, Set<Class<?>> classes) {
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 100644
--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo;
public class ServerModNameConfig implements IConfigModule {
@ConfigInfo(baseName = "name")
- public static String serverModName = "Luminol";
+ public static String serverModName = "Lophine";
@ConfigInfo(baseName = "vanilla_spoof")
public static boolean fakeVanilla = false;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..1c3b94a2592cff74924cf9b355e30b0fa182b79b 100644
index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..2c546d470013d4daf3ddf427ab4bda1b51d6e641 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java
@@ -11,7 +11,7 @@ public final class Versioning {
@@ -407,7 +99,7 @@ index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..1c3b94a2592cff74924cf9b355e30b0f
String result = "Unknown-Version";
- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.luminol/luminol-api/pom.properties"); // Folia //Luminol
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.lophine/lophine-api/pom.properties"); // Folia //Luminol
+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/fun.bm.lophine/lophine-api/pom.properties"); // Folia //Luminol
Properties properties = new Properties();
if (stream != null) {
@@ -5,17 +5,17 @@ Subject: [PATCH] Purpur-Barrels-and-enderchests-6-rows
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
index c00ddfe41439954fa0fd87c0933f274c8a752eb6..ac0218fcdf9e9c77a30b7f09b2a5e557ef0f7591 100644
index 2f41a92465b9da28e026297cc3528898bb1c8412..fb5300ec1bd19b3dfd6a2b4106440b9f73c48205 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
@@ -150,9 +150,26 @@ public class CraftContainer extends AbstractContainerMenu {
@@ -148,9 +148,26 @@ public class CraftContainer extends AbstractContainerMenu {
case PLAYER:
case CHEST:
case ENDER_CHEST:
- case BARREL:
- this.delegate = new ChestMenu(net.minecraft.world.inventory.MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
+ // Purpur start - Barrels and enderchests 6 rows
+ this.delegate = new ChestMenu(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ this.delegate = new ChestMenu(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6;
+ case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5;
+ case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4;
@@ -25,7 +25,7 @@ index c00ddfe41439954fa0fd87c0933f274c8a752eb6..ac0218fcdf9e9c77a30b7f09b2a5e557
+ }, windowId, bottom, top, top.getContainerSize() / 9);
break;
+ case BARREL:
+ this.delegate = new ChestMenu(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ this.delegate = new ChestMenu(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6;
+ case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5;
+ case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4;
@@ -1,154 +0,0 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/CullTask.java
@@ -1,0 +_,151 @@
+package dev.tr7zw.entityculling;
+
+import ca.spottedleaf.moonrise.common.util.TickThread;
+import com.logisticscraft.occlusionculling.OcclusionCullingInstance;
+import com.logisticscraft.occlusionculling.util.Vec3d;
+import dev.tr7zw.entityculling.versionless.access.Cullable;
+import me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.decoration.ArmorStand;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class CullTask implements Runnable {
+
+ private volatile boolean requestCull = false;
+ private volatile boolean scheduleNext = true;
+ private volatile boolean inited = false;
+
+ private final OcclusionCullingInstance culling;
+ private final Player checkTarget;
+
+ private final int hitboxLimit;
+
+ public long lastCheckedTime = 0;
+
+ // reused preallocated vars
+ private final Vec3d lastPos = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMin = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMax = new Vec3d(0, 0, 0);
+
+ private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> {
+ final TickThread worker = new TickThread("EntityCulling") {
+ @Override
+ public void run() {
+ task.run();
+ }
+ };
+
+ worker.setDaemon(true);
+
+ return worker;
+ });
+
+ private final Executor worker;
+
+ public CullTask(
+ OcclusionCullingInstance culling,
+ Player checkTarget,
+ int hitboxLimit,
+ long checkIntervalMs
+ ) {
+ this.culling = culling;
+ this.checkTarget = checkTarget;
+ this.hitboxLimit = hitboxLimit;
+ this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker);
+ }
+
+ public void requestCullSignal() {
+ this.requestCull = true;
+ }
+
+ public void signalStop() {
+ this.scheduleNext = false;
+ }
+
+ public void setup() {
+ if (!this.inited)
+ this.inited = true;
+ else
+ return;
+ this.worker.execute(this);
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (this.checkTarget.tickCount > 10) {
+ // getEyePosition can use a fixed delta as its debug only anyway
+ Vec3 cameraMC = this.checkTarget.getEyePosition(0);
+ if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) {
+ long start = System.currentTimeMillis();
+
+ requestCull = false;
+
+ lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z);
+ culling.resetCache();
+
+ cullEntities(cameraMC, lastPos);
+
+ lastCheckedTime = (System.currentTimeMillis() - start);
+ }
+ }
+ }finally {
+ if (this.scheduleNext) {
+ this.worker.execute(this);
+ }
+ }
+ }
+
+ private void cullEntities(Vec3 cameraMC, Vec3d camera) {
+ for (Entity entity : this.checkTarget.level().getEntities().getAll()) {
+ if (!(entity instanceof Cullable cullable)) {
+ continue; // Not sure how this could happen outside from mixin screwing up the inject into
+ // Entity
+ }
+
+ if (entity.getType().skipRaytracningCheck) {
+ continue;
+ }
+
+ if (!cullable.isForcedVisible()) {
+ if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) {
+ cullable.setCulled(false);
+ continue;
+ }
+
+ if (!entity.position().closerThan(cameraMC, RayTrackingEntityTrackerConfig.tracingDistance)) {
+ cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just
+ // render it
+ continue;
+ }
+
+ AABB boundingBox = entity.getBoundingBox();
+ if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit
+ || boundingBox.getZsize() > hitboxLimit) {
+ cullable.setCulled(false); // Too big to bother to cull
+ continue;
+ }
+
+ aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ);
+ aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ);
+
+ boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera);
+
+ cullable.setCulled(!visible);
+ }
+ }
+ }
+
+ private boolean isSkippableArmorstand(Entity entity) {
+ if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands)
+ return false;
+ return entity instanceof ArmorStand && entity.isInvisible();
+ }
+}
@@ -1,45 +0,0 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java
@@ -1,0 +_,42 @@
+package dev.tr7zw.entityculling;
+
+import com.logisticscraft.occlusionculling.DataProvider;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.chunk.ChunkAccess;
+
+public class DefaultChunkDataProvider implements DataProvider {
+ private final Level level;
+
+ public DefaultChunkDataProvider(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public boolean prepareChunk(int chunkX, int chunkZ) {
+ return this.level.getChunkIfLoaded(chunkX, chunkZ) != null;
+ }
+
+ @Override
+ public boolean isOpaqueFullCube(int x, int y, int z) {
+ BlockPos pos = new BlockPos(x, y, z);
+
+ final ChunkAccess access = this.level.getChunkIfLoaded(pos);
+ if (access == null) {
+ return false;
+ }
+
+ if (this.level.isOutsideBuildHeight(pos)) {
+ return Blocks.VOID_AIR.defaultBlockState().isSolidRender();
+ } else {
+ return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截()
+ }
+ }
+
+ @Override
+ public void cleanup() {
+ DataProvider.super.cleanup();
+ }
+
+}
@@ -1,20 +0,0 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java
@@ -1,0 +_,17 @@
+package dev.tr7zw.entityculling.versionless.access;
+
+public interface Cullable {
+
+ public void setTimeout();
+
+ public boolean isForcedVisible();
+
+ public void setCulled(boolean value);
+
+ public boolean isCulled();
+
+ public void setOutOfCamera(boolean value);
+
+ public boolean isOutOfCamera();
+
+}
@@ -1,36 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/LophineConfig.java
@@ -1,0 +_,33 @@
+package me.earthme.lophine.config;
+
+import me.earthme.luminol.config.LuminolConfig;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class LophineConfig {
+ public static final Map<String, LuminolConfig> configfiles = new HashMap<>();
+ private static final File luminolConfigFolder = new File("luminol_config");
+ private static final File lophineConfigFolder = new File("lophine_config");
+
+ public static void initConfigs() throws IOException {
+ configfiles.put("luminol", new LuminolConfig(luminolConfigFolder, "luminol", "me.earthme.luminol.config.modules"));
+ configfiles.put("lophine", new LuminolConfig(lophineConfigFolder, "lophine", "me.earthme.lophine.config.modules"));
+ preLoad();
+ }
+
+ public static void preLoad() throws IOException {
+ for (LuminolConfig config : configfiles.values()) {
+ config.preLoadConfig();
+ }
+ }
+
+ public static void loadConfigFiles() {
+ for (LuminolConfig config : configfiles.values()) {
+ config.finalizeLoadConfig();
+ config.setupLatch();
+ }
+ }
+}
@@ -1,30 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java
@@ -1,0 +_,27 @@
+package me.earthme.lophine.config.modules.experiment;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class CommandConfig implements IConfigModule {
+ @ConfigInfo(baseName = "command_block_enabled", comments =
+ """
+ Allow to use command block""")
+ public static boolean block = false;
+
+ @ConfigInfo(baseName = "tick_command_enabled", comments =
+ """
+ Allow to use tick command""")
+ public static boolean tick = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.EXPERIMENT;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "command";
+ }
+}
@@ -1,25 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java
@@ -1,0 +_,22 @@
+package me.earthme.lophine.config.modules.experiment;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class EntityDamageSourceTraceConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled", comments =
+ """
+ Allow trace damage source cross different Region Scheduler.""")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.EXPERIMENT;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "entity_damage_source_trace";
+ }
+}
@@ -1,31 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java
@@ -1,0 +_,28 @@
+package me.earthme.lophine.config.modules.experiment;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class RayTrackingEntityTrackerConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+ @ConfigInfo(baseName = "skip_marker_armor_stands")
+ public static boolean skipMarkerArmorStands = true;
+ @ConfigInfo(baseName = "check_interval_ms")
+ public static int checkIntervalMs = 10;
+ @ConfigInfo(baseName = "tracing_distance")
+ public static int tracingDistance = 48;
+ @ConfigInfo(baseName = "hitbox_limit")
+ public static int hitboxLimit = 50;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.EXPERIMENT;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "ray_tracking_entity_tracker";
+ }
+}
@@ -1,40 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java
@@ -1,0 +_,37 @@
+package me.earthme.lophine.config.modules.misc;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class ContainerExpansionConfig implements IConfigModule {
+ @ConfigInfo(baseName = "barrel_rows", comments =
+ """
+ range: 1~6""")
+ public static int barrelRows = 3;
+
+ @ConfigInfo(baseName = "enderchest_rows", comments =
+ """
+ range: 1~6""")
+ public static int enderchestRows = 3;
+
+ @ConfigInfo(baseName = "shulker_stackable_count", comments =
+ """
+ range: 1~64""")
+ public static int shulkerCount = 1;
+
+ @ConfigInfo(baseName = "better_shulker_box", comments =
+ """
+ Enable sneak + use to open shulker box.""")
+ public static boolean betterShulker = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "container_expansion";
+ }
+}
@@ -1,26 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java
@@ -1,0 +_,23 @@
+package me.earthme.lophine.config.modules.misc;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class DisableEndCrystalCheckConfig implements IConfigModule {
+ @ConfigInfo(baseName = "disable_end_crystal_check", comments =
+ """
+ Disable paper's End Crystal position check.
+ It reverts to vanilla respawn dragon logic.""")
+ public static boolean disableCheck = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "end_crystal";
+ }
+}
@@ -1,29 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java
@@ -1,0 +_,26 @@
+package me.earthme.lophine.config.modules.misc;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class OldFeatureConfig implements IConfigModule {
+ @ConfigInfo(baseName = "old_nether_portal_collision")
+ public static boolean oldNetherPortalCollision = false;
+
+ @ConfigInfo(baseName = "spawn_invulnerable_time")
+ public static boolean spawnInvulnerableTime = false;
+
+ @ConfigInfo(baseName = "old_zombie_reinforcement")
+ public static boolean oldZombieReinforcement = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "old-feature";
+ }
+}
@@ -1,57 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java
@@ -1,0 +_,54 @@
+package me.earthme.lophine.config.modules.misc;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class RaidChangesConfig implements IConfigModule {
+ @ConfigInfo(baseName = "allow_skip_cooldown", comments =
+ """
+ Allow players with bad omen to skip a
+ 30-second cooldown and trigger attacks directly""")
+ public static boolean trigger = false;
+
+ @ConfigInfo(baseName = "give_bad_omen_when_kill_raid_captain", comments =
+ """
+ Enable players to obtain a bad omen
+ effect when killing the raid captain""")
+ public static boolean effect = false;
+
+ @ConfigInfo(baseName = "bad_omen_infinite", comments =
+ """
+ Enable bad omen effect infinite time
+ --- this config is not old version's function""")
+ public static boolean infinite = false;
+
+ @ConfigInfo(baseName = "skip_height_check", comments =
+ """
+ Disable y <= 96 check.
+ If you enabled use_old_position_find, this config
+ will useless and always behavior of enabled""")
+ public static boolean heightCheck = false;
+
+ @ConfigInfo(baseName = "skip_self_raid_check", comments =
+ """
+ Disable raid self check
+ --- this config is not old version's function""")
+ public static boolean selfCheck = false;
+
+ @ConfigInfo(baseName = "use_old_position_find", comments =
+ """
+ Revert Old raid's find spawn position logic
+ --- This revert MC-274911""")
+ public static boolean posRevert = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "revert_raid_changes";
+ }
+}
@@ -1,25 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java
@@ -1,0 +_,22 @@
+package me.earthme.lophine.config.modules.optimizations;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class LanguageConfig implements IConfigModule {
+ @ConfigInfo(baseName = "lang", comments = """
+ Please use the key from https://minecraft.wiki/w/Language
+ Sample of format: en_us zh_cn zh_hk zh_tw""")
+ public static String lang = "en_us";
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.OPTIMIZATIONS;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "language";
+ }
+}
@@ -1,27 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java
@@ -1,0 +_,24 @@
+package me.earthme.lophine.config.modules.removed;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+import me.earthme.luminol.config.flags.TransformedConfig;
+
+public class RemovedConfig implements IConfigModule {
+ @TransformedConfig(name = "example", category = {"removed", "example"}, transform = false)
+ @ConfigInfo(baseName = "removed", comments =
+ """
+ RemovedConfig redirect to here, no any function.""")
+ public static boolean enabled = true;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.REMOVED;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "removed_config";
+ }
+}
@@ -1,254 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java
@@ -1,0 +_,251 @@
+package me.earthme.lophine.utils;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import me.earthme.lophine.config.modules.optimizations.LanguageConfig;
+import net.minecraft.locale.DeprecatedTranslationsInfo;
+import net.minecraft.locale.Language;
+import net.minecraft.network.chat.FormattedText;
+import net.minecraft.network.chat.Style;
+import net.minecraft.util.FormattedCharSequence;
+import net.minecraft.util.StringDecomposer;
+import org.apache.commons.io.FileUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiConsumer;
+import java.util.logging.Logger;
+
+/*
+* authored by: Helvetica Volubi <suisuroru@blue-millennium.fun>
+* modified by: Lumine1909 <133463833+Lumine1909@users.noreply.github.com>
+* Some of diff form Leaves
+*/
+public class ServerI18nUtil {
+
+ private static final Logger logger = Logger.getLogger("LangLoader");
+ private static final String VERSION = "1.21.5";
+ private static final String BASE_PATH = "cache/lophine/" + VERSION + "/";
+ private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
+ private static final String resourceBaseUrl = "https://resources.download.minecraft.net/";
+
+ private static String langPath;
+ private static String assetsPath;
+ private static String versionPath;
+ private static String manifestPath;
+ private static String langJsonPath;
+
+ public static void init() {
+ if (Objects.equals(LanguageConfig.lang, "en_us")) {
+ return;
+ }
+ langPath = BASE_PATH + "lang/" + LanguageConfig.lang + ".json";
+ assetsPath = BASE_PATH + "assets.json";
+ versionPath = BASE_PATH + VERSION + ".json";
+ manifestPath = BASE_PATH + "manifest.json";
+ langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json";
+ logger.info("Starting load language: " + LanguageConfig.lang);
+ CompletableFuture.runAsync(() -> loadI18n(LanguageConfig.lang, 2));
+ }
+
+ private static void loadI18n(String lang, int retryTime) {
+ try {
+ if (!Files.exists(Path.of(langPath))) {
+ downloadLang(true);
+ }
+ Language.inject(createLangInstance());
+ logger.info("Successfully loaded language: " + lang);
+ } catch (Exception e) {
+ logger.warning("Failed to load language file for " + lang + "\n" + e);
+ if (retryTime > 0) {
+ cleanCache();
+ loadI18n(lang, retryTime - 1);
+ } else {
+ logger.severe("Failed to load for many times, use default lang \"en_us\" instead");
+ cleanCache();
+ }
+ }
+ }
+
+ private static void downloadLang(boolean fetchFromAssets) throws Exception {
+ JsonObject json;
+ if (!Files.exists(Path.of(assetsPath)) || (json = loadJson(assetsPath)) == null) {
+ if (fetchFromAssets) {
+ downloadAssets(true);
+ downloadLang(false);
+ }
+ return;
+ }
+
+ JsonObject langEntry = json.getAsJsonObject("objects").getAsJsonObject(langJsonPath);
+
+ String hash = langEntry.get("hash").getAsString();
+ if (hash == null || hash.length() < 2) {
+ throw new IllegalArgumentException("Invalid hash value");
+ }
+
+ String langUrl = resourceBaseUrl + hash.substring(0, 2) + "/" + hash;
+ fetchAndSave(langUrl, langPath);
+ }
+
+ private static void downloadAssets(boolean fetchFromVersion) throws Exception {
+ JsonObject json;
+ if (!Files.exists(Path.of(versionPath)) || (json = loadJson(versionPath)) == null) {
+ if (fetchFromVersion) {
+ downloadVersion(true);
+ downloadAssets(false);
+ }
+ return;
+ }
+
+ JsonObject assetIndex = json.getAsJsonObject("assetIndex");
+ String assetUrl = assetIndex.get("url").getAsString();
+ fetchAndSave(assetUrl, assetsPath);
+ }
+
+ private static void downloadVersion(boolean fetchFromManifest) throws Exception {
+ JsonObject json;
+ if (!Files.exists(Path.of(manifestPath)) || (json = loadJson(manifestPath)) == null) {
+ if (fetchFromManifest) {
+ fetchAndSave(manifestUrl, manifestPath);
+ downloadVersion(false);
+ }
+ return;
+ }
+
+ String versionUrl = null;
+ for (JsonElement element : json.getAsJsonArray("versions")) {
+ String id = element.getAsJsonObject().get("id").getAsString();
+ String url = element.getAsJsonObject().get("url").getAsString();
+ if (VERSION.equals(id)) {
+ versionUrl = url;
+ break;
+ }
+ }
+
+ if (versionUrl == null) {
+ throw new RuntimeException("Could not find version URL");
+ }
+
+ fetchAndSave(versionUrl, versionPath);
+ }
+
+ private static String createHttpResponse(String path) throws IOException, InterruptedException {
+ try {
+ HttpResponse<String> response;
+ try (HttpClient httpClient = HttpClient.newHttpClient()) {
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(path))
+ .build();
+
+ response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+
+ int responseCode = response.statusCode();
+ if (responseCode != 200) {
+ logger.info("Unexpected response code: " + responseCode);
+ logger.info("Response body: " + response.body());
+ throw new UnsupportedEncodingException("Unexpected response code");
+ } else {
+ return response.body();
+ }
+ } catch (Exception e) {
+ logger.warning("Error in getting info: " + e.getMessage());
+ throw e;
+ }
+ }
+
+ private static byte[] fetch(String urlString) throws IOException, InterruptedException {
+ String ret = createHttpResponse(urlString);
+ return ret.getBytes();
+ }
+
+ private static void fetchAndSave(String url, String savePath) throws IOException, InterruptedException {
+ byte[] data = fetch(url);
+ Path outputPath = Path.of(savePath);
+ Files.createDirectories(outputPath.getParent());
+ Files.write(outputPath, data, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
+ }
+
+ private static void cleanCache() {
+ try {
+ FileUtils.deleteDirectory(Path.of(BASE_PATH).toFile());
+ } catch (IOException e) {
+ logger.severe("Cache cleanup failed: " + e);
+ }
+ }
+
+ private static JsonObject loadJson(String path) {
+ try {
+ byte[] data = Files.readAllBytes(Paths.get(path));
+ return JsonParser.parseString(new String(data)).getAsJsonObject();
+ } catch (JsonSyntaxException e) {
+ logger.warning("Corrupt json file: " + e);
+ throw e;
+ } catch (Exception e) {
+ logger.warning("Failed to load local JSON: " + e);
+ return null;
+ }
+ }
+
+ private static Language createLangInstance() throws IOException {
+ DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource();
+ Map<String, String> map = new HashMap<>();
+ parseTranslations(map::put);
+ deprecatedTranslationsInfo.applyToMap(map);
+ final Map<String, String> map1 = Map.copyOf(map);
+ return new Language() {
+ @Override
+ public @NotNull String getOrDefault(@NotNull String key, @NotNull String defaultValue) {
+ return map1.getOrDefault(key, defaultValue);
+ }
+
+ @Override
+ public boolean has(@NotNull String id) {
+ return map1.containsKey(id);
+ }
+
+ @Override
+ public boolean isDefaultRightToLeft() {
+ return false;
+ }
+
+ @Override
+ public @NotNull FormattedCharSequence getVisualOrder(@NotNull FormattedText text) {
+ return sink -> text.visit(
+ (style, content) -> StringDecomposer.iterateFormatted(content, style, sink) ? Optional.empty() : FormattedText.STOP_ITERATION,
+ Style.EMPTY
+ )
+ .isPresent();
+ }
+ };
+ }
+
+ private static void parseTranslations(BiConsumer<String, String> output) throws IOException {
+ Path filePath = Path.of(langPath);
+ try (InputStream fileStream = Files.newInputStream(filePath)) {
+ Language.loadFromJson(fileStream, output);
+ } catch (NoSuchFileException noSuchFileException) {
+ logger.warning("Couldn't find language file: " + langPath);
+ throw noSuchFileException;
+ } catch (Exception e) {
+ logger.warning("Failed to load language from filesystem " + filePath + "\n" + e);
+ throw e;
+ }
+ }
+}
@@ -1,156 +0,0 @@
--- /dev/null
+++ b/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java
@@ -1,0 +_,153 @@
+package me.earthme.lophine.utils;
+
+import me.earthme.lophine.config.modules.misc.ContainerExpansionConfig;
+import net.minecraft.core.NonNullList;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.stats.Stats;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.BlockItem;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.item.component.ItemContainerContents;
+import net.minecraft.world.level.block.ShulkerBoxBlock;
+import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import static net.minecraft.world.inventory.AbstractContainerMenu.dropOrPlaceInInventory;
+
+public class ShulkerBoxesUtil {
+ // Stackable ShulkerBoxes part
+ public static boolean shouldCheck() {
+ return ContainerExpansionConfig.shulkerCount > 1 && ContainerExpansionConfig.shulkerCount <= 64;
+ }
+
+ public static boolean checkShulkerBox(ItemStack itemStack) {
+ return shouldCheck() && checkIsShulkerBox(itemStack);
+ }
+
+ public static boolean checkIsShulkerBox(ItemStack itemStack) {
+ return itemStack.getItem() instanceof BlockItem b && b.getBlock() instanceof ShulkerBoxBlock;
+ }
+
+ public static int getItemMaxCount(ItemStack itemStack) {
+ if (checkShulkerBox(itemStack)) {
+ return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64);
+ }
+ return itemStack.getMaxStackSize();
+ }
+
+ public static int getShulkerBoxesMaxCountUnsafe() {
+ return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64);
+ }
+
+ public static boolean emptyShulkerBoxCheck(@NotNull ItemStack stack) {
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
+ }
+
+ public static boolean isStackable(ItemStack itemStack) {
+ return getItemMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
+ }
+
+ public static int getItemStackMaxCountReal(ItemStack stack) {
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
+ return nbt.getInt("Lophine.RealStackSize").orElse(stack.getMaxStackSize());
+ }
+
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
+ int modifiedMaxStackSize = getItemMaxCount(itemStack);
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
+ nbt.putInt("Lophine.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("Lophine.RealStackSize");
+ if (nbt.isEmpty()) {
+ itemStack.remove(DataComponents.CUSTOM_DATA);
+ } else {
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
+ }
+ }
+ return itemStack;
+ }
+
+ // Better ShulkerBox part
+ public static boolean checkIfCanOpen(ItemStack itemStack) {
+ return checkIsShulkerBox(itemStack) && itemStack.getCount() == 1;
+ }
+
+ public static void openShulkerBox(Player player, ItemStack itemInHand, InteractionHand hand) {
+ ShulkerBoxBlockEntity shulkerBoxEntity = new ShulkerBoxBlockEntity(
+ player.blockPosition(),
+ ((BlockItem) itemInHand.getItem()).getBlock().defaultBlockState()
+ );
+ ItemContainerContents container = itemInHand.getOrDefault(
+ DataComponents.CONTAINER,
+ ItemContainerContents.EMPTY
+ );
+
+ NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
+ for (int i = 0; i < container.items.size(); i++) {
+ items.set(i, container.items.get(i));
+ }
+
+ shulkerBoxEntity.setItems(items);
+
+ shulkerBoxEntity.setLevel(player.level());
+ shulkerBoxEntity.haveRealBlock = false;
+ shulkerBoxEntity.createPlayer = player;
+ player.shulkerHand = hand;
+ player.shulkerOpen = true;
+
+ if (player.openMenu(shulkerBoxEntity).isPresent()) {
+ player.awardStat(Stats.OPEN_SHULKER_BOX);
+ }
+ }
+
+ public static void shulkerBoxEntityCallBack(ShulkerBoxBlockEntity shulkerBoxEntity) {
+ Player player = shulkerBoxEntity.createPlayer;
+ if (player.shulkerOpen) {
+ InteractionHand hand = player.shulkerHand;
+ ItemStack currentItem = player.getItemInHand(hand);
+
+ currentItem.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(shulkerBoxEntity.getItems()));
+
+ player.setItemInHand(hand, currentItem);
+ }
+ }
+
+ public static void inventoryCallBack(boolean isMainHand, Player player) {
+ if (player.shulkerOpen) {
+ if (isMainHand == Objects.equals(player.shulkerHand, InteractionHand.MAIN_HAND)) {
+ player.pendingClosingShulker = true;
+ closeScreen(player);
+ player.pendingClosingShulker = false;
+ }
+ }
+ }
+
+ public static void closeScreen(Player player) {
+ if (player instanceof ServerPlayer) {
+ ItemStack stack = player.containerMenu.getCarried();
+ if (!stack.isEmpty()) {
+ dropOrPlaceInInventory(player, stack);
+ }
+ }
+ player.closeContainer();
+ }
+}
@@ -0,0 +1,151 @@
package dev.tr7zw.entityculling;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.logisticscraft.occlusionculling.OcclusionCullingInstance;
import com.logisticscraft.occlusionculling.util.Vec3d;
import dev.tr7zw.entityculling.versionless.access.Cullable;
import fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CullTask implements Runnable {
private volatile boolean requestCull = false;
private volatile boolean scheduleNext = true;
private volatile boolean inited = false;
private final OcclusionCullingInstance culling;
private final Player checkTarget;
private final int hitboxLimit;
public long lastCheckedTime = 0;
// reused preallocated vars
private final Vec3d lastPos = new Vec3d(0, 0, 0);
private final Vec3d aabbMin = new Vec3d(0, 0, 0);
private final Vec3d aabbMax = new Vec3d(0, 0, 0);
private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> {
final TickThread worker = new TickThread("EntityCulling") {
@Override
public void run() {
task.run();
}
};
worker.setDaemon(true);
return worker;
});
private final Executor worker;
public CullTask(
OcclusionCullingInstance culling,
Player checkTarget,
int hitboxLimit,
long checkIntervalMs
) {
this.culling = culling;
this.checkTarget = checkTarget;
this.hitboxLimit = hitboxLimit;
this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker);
}
public void requestCullSignal() {
this.requestCull = true;
}
public void signalStop() {
this.scheduleNext = false;
}
public void setup() {
if (!this.inited)
this.inited = true;
else
return;
this.worker.execute(this);
}
@Override
public void run() {
try {
if (this.checkTarget.tickCount > 10) {
// getEyePosition can use a fixed delta as its debug only anyway
Vec3 cameraMC = this.checkTarget.getEyePosition(0);
if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) {
long start = System.currentTimeMillis();
requestCull = false;
lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z);
culling.resetCache();
cullEntities(cameraMC, lastPos);
lastCheckedTime = (System.currentTimeMillis() - start);
}
}
} finally {
if (this.scheduleNext) {
this.worker.execute(this);
}
}
}
private void cullEntities(Vec3 cameraMC, Vec3d camera) {
for (Entity entity : this.checkTarget.level().getEntities().getAll()) {
if (!(entity instanceof Cullable cullable)) {
continue; // Not sure how this could happen outside from mixin screwing up the inject into
// Entity
}
if (entity.getType().skipRaytracningCheck) {
continue;
}
if (!cullable.isForcedVisible()) {
if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) {
cullable.setCulled(false);
continue;
}
if (!entity.position().closerThan(cameraMC, RayTrackingEntityTrackerConfig.tracingDistance)) {
cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just
// render it
continue;
}
AABB boundingBox = entity.getBoundingBox();
if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit
|| boundingBox.getZsize() > hitboxLimit) {
cullable.setCulled(false); // Too big to bother to cull
continue;
}
aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ);
aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ);
boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera);
cullable.setCulled(!visible);
}
}
}
private boolean isSkippableArmorstand(Entity entity) {
if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands)
return false;
return entity instanceof ArmorStand && entity.isInvisible();
}
}
@@ -0,0 +1,42 @@
package dev.tr7zw.entityculling;
import com.logisticscraft.occlusionculling.DataProvider;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
public class DefaultChunkDataProvider implements DataProvider {
private final Level level;
public DefaultChunkDataProvider(Level level) {
this.level = level;
}
@Override
public boolean prepareChunk(int chunkX, int chunkZ) {
return this.level.getChunkIfLoaded(chunkX, chunkZ) != null;
}
@Override
public boolean isOpaqueFullCube(int x, int y, int z) {
BlockPos pos = new BlockPos(x, y, z);
final ChunkAccess access = this.level.getChunkIfLoaded(pos);
if (access == null) {
return false;
}
if (this.level.isOutsideBuildHeight(pos)) {
return Blocks.VOID_AIR.defaultBlockState().isSolidRender();
} else {
return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截()
}
}
@Override
public void cleanup() {
DataProvider.super.cleanup();
}
}
@@ -0,0 +1,17 @@
package dev.tr7zw.entityculling.versionless.access;
public interface Cullable {
public void setTimeout();
public boolean isForcedVisible();
public void setCulled(boolean value);
public boolean isCulled();
public void setOutOfCamera(boolean value);
public boolean isOutOfCamera();
}
@@ -0,0 +1,28 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class CommandConfig implements IConfigModule {
@ConfigInfo(baseName = "tick_command_enabled", comments =
"""
Allow to use tick command""")
public static boolean tick = false;
@ConfigInfo(baseName = "datapack_command_enabled", comments =
"""
Allow to use datapack command
--- datapack hot-update unsupported, please restart server""")
public static boolean datapack = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.EXPERIMENT;
}
@Override
public String getBaseName() {
return "command";
}
}
@@ -0,0 +1,22 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class EntityDamageSourceTraceConfig implements IConfigModule {
@ConfigInfo(baseName = "enabled", comments =
"""
Allow trace damage source cross different Region Scheduler.""")
public static boolean enabled = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.EXPERIMENT;
}
@Override
public String getBaseName() {
return "entity_damage_source_trace";
}
}
@@ -0,0 +1,28 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class RayTrackingEntityTrackerConfig implements IConfigModule {
@ConfigInfo(baseName = "enabled")
public static boolean enabled = false;
@ConfigInfo(baseName = "skip_marker_armor_stands")
public static boolean skipMarkerArmorStands = true;
@ConfigInfo(baseName = "check_interval_ms")
public static int checkIntervalMs = 10;
@ConfigInfo(baseName = "tracing_distance")
public static int tracingDistance = 48;
@ConfigInfo(baseName = "hitbox_limit")
public static int hitboxLimit = 50;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.EXPERIMENT;
}
@Override
public String getBaseName() {
return "ray_tracking_entity_tracker";
}
}
@@ -0,0 +1,24 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
public class WaypointConfig implements IConfigModule {
@TransformedConfig(name = "enable-waypoint", category = {"experiment", "waypoint bar"})
@ConfigInfo(baseName = "enabled", comments =
"""
Enable waypoint bar unsafe""")
public static boolean forceEnableWaypointUnsafe = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.EXPERIMENT;
}
@Override
public String getBaseName() {
return "waypoint_bar";
}
}
@@ -0,0 +1,32 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class ContainerExpansionConfig implements IConfigModule {
@ConfigInfo(baseName = "barrel_rows", comments =
"""
range: 1~6""")
public static int barrelRows = 3;
@ConfigInfo(baseName = "enderchest_rows", comments =
"""
range: 1~6""")
public static int enderchestRows = 3;
@ConfigInfo(baseName = "shulker_stackable_count", comments =
"""
range: 1~64""")
public static int shulkerCount = 1;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "container_expansion";
}
}
@@ -0,0 +1,23 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class DisableEndCrystalCheckConfig implements IConfigModule {
@ConfigInfo(baseName = "disable_end_crystal_check", comments =
"""
Disable paper's End Crystal position check.
It reverts to vanilla respawn dragon logic.""")
public static boolean disableCheck = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "end_crystal";
}
}
@@ -0,0 +1,29 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class OldFeatureConfig implements IConfigModule {
@ConfigInfo(baseName = "spawn_invulnerable_time")
public static boolean spawnInvulnerableTime = false;
@ConfigInfo(baseName = "old_zombie_reinforcement")
public static boolean oldZombieReinforcement = false;
@ConfigInfo(baseName = "old_replaceable_by_mushrooms")
public static boolean oldReplaceableByMushrooms = false;
@ConfigInfo(baseName = "old_explosion_damage_calculator")
public static boolean oldExplosionDamageCalculator = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "old-feature";
}
}
@@ -0,0 +1,54 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class RaidChangesConfig implements IConfigModule {
@ConfigInfo(baseName = "allow_skip_cooldown", comments =
"""
Allow players with bad omen to skip a
30-second cooldown and trigger attacks directly""")
public static boolean trigger = false;
@ConfigInfo(baseName = "give_bad_omen_when_kill_raid_captain", comments =
"""
Enable players to obtain a bad omen
effect when killing the raid captain""")
public static boolean effect = false;
@ConfigInfo(baseName = "bad_omen_infinite", comments =
"""
Enable bad omen effect infinite time
--- this config is not old version's function""")
public static boolean infinite = false;
@ConfigInfo(baseName = "skip_height_check", comments =
"""
Disable y <= 96 check.
If you enabled use_old_position_find, this config
will useless and always behavior of enabled""")
public static boolean heightCheck = false;
@ConfigInfo(baseName = "skip_self_raid_check", comments =
"""
Disable raid self check
--- this config is not old version's function""")
public static boolean selfCheck = false;
@ConfigInfo(baseName = "use_old_position_find", comments =
"""
Revert Old raid's find spawn position logic
--- This revert MC-274911""")
public static boolean posRevert = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "revert_raid_changes";
}
}
@@ -0,0 +1,21 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class RedStoneConfig implements IConfigModule {
@ConfigInfo(baseName = "allow_skip_cooldown", comments =
"""
Allows you to use the Shears to right-click to rotate the block.""")
public static boolean shears = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "redstone";
}
}
@@ -0,0 +1,23 @@
package fun.bm.lophine.config.modules.misc;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class VillagerConfig implements IConfigModule {
@ConfigInfo(baseName = "villager-infinite-trade", comments =
"""
Allow villager infinite trade (limit of 16384 times)
---- we won't edit saved data, only edit in send data to client.""")
public static boolean villagerInfiniteTrade = false;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.MISC;
}
@Override
public String getBaseName() {
return "villager-config";
}
}
@@ -0,0 +1,22 @@
package fun.bm.lophine.config.modules.optimizations;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
public class LanguageConfig implements IConfigModule {
@ConfigInfo(baseName = "lang", comments = """
Please use the key from https://minecraft.wiki/w/Language
Sample of format: en_us zh_cn zh_hk zh_tw""")
public static String lang = "en_us";
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.OPTIMIZATIONS;
}
@Override
public String getBaseName() {
return "language";
}
}
@@ -0,0 +1,25 @@
package fun.bm.lophine.config.modules.removed;
import me.earthme.luminol.config.EnumConfigCategory;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
public class RemovedConfig implements IConfigModule {
@TransformedConfig(name = "old_nether_portal_collision", category = {"misc", "old-feature"}, transform = false)
@TransformedConfig(name = "better_shulker_box", category = {"misc", "container_expansion"}, transform = false)
@ConfigInfo(baseName = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
public static boolean enabled = true;
@Override
public EnumConfigCategory getCategory() {
return EnumConfigCategory.REMOVED;
}
@Override
public String getBaseName() {
return "removed_config";
}
}
@@ -0,0 +1,252 @@
package fun.bm.lophine.utils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import fun.bm.lophine.config.modules.optimizations.LanguageConfig;
import net.minecraft.DetectedVersion;
import net.minecraft.locale.DeprecatedTranslationsInfo;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.StringDecomposer;
import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.logging.Logger;
/*
* authored by: Helvetica Volubi <suisuroru@blue-millennium.fun>
* modified by: Lumine1909 <133463833+Lumine1909@users.noreply.github.com>
* Some of diff form Leaves
*/
public class ServerI18nUtil {
private static final Logger logger = Logger.getLogger("LangLoader");
private static final String VERSION = DetectedVersion.BUILT_IN.name();
private static final String BASE_PATH = "cache/lophine/" + VERSION + "/";
private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
private static final String resourceBaseUrl = "https://resources.download.minecraft.net/";
private static String langPath;
private static String assetsPath;
private static String versionPath;
private static String manifestPath;
private static String langJsonPath;
public static void init() {
if (Objects.equals(LanguageConfig.lang, "en_us")) {
return;
}
langPath = BASE_PATH + "lang/" + LanguageConfig.lang + ".json";
assetsPath = BASE_PATH + "assets.json";
versionPath = BASE_PATH + VERSION + ".json";
manifestPath = BASE_PATH + "manifest.json";
langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json";
logger.info("Starting load language: " + LanguageConfig.lang);
CompletableFuture.runAsync(() -> loadI18n(LanguageConfig.lang, 2));
}
private static void loadI18n(String lang, int retryTime) {
try {
if (!Files.exists(Path.of(langPath))) {
downloadLang(true);
}
Language.inject(createLangInstance());
logger.info("Successfully loaded language: " + lang);
} catch (Exception e) {
logger.warning("Failed to load language file for " + lang + "\n" + e);
if (retryTime > 0) {
cleanCache();
loadI18n(lang, retryTime - 1);
} else {
logger.severe("Failed to load for many times, use default lang \"en_us\" instead");
cleanCache();
}
}
}
private static void downloadLang(boolean fetchFromAssets) throws Exception {
JsonObject json;
if (!Files.exists(Path.of(assetsPath)) || (json = loadJson(assetsPath)) == null) {
if (fetchFromAssets) {
downloadAssets(true);
downloadLang(false);
}
return;
}
JsonObject langEntry = json.getAsJsonObject("objects").getAsJsonObject(langJsonPath);
String hash = langEntry.get("hash").getAsString();
if (hash == null || hash.length() < 2) {
throw new IllegalArgumentException("Invalid hash value");
}
String langUrl = resourceBaseUrl + hash.substring(0, 2) + "/" + hash;
fetchAndSave(langUrl, langPath);
}
private static void downloadAssets(boolean fetchFromVersion) throws Exception {
JsonObject json;
if (!Files.exists(Path.of(versionPath)) || (json = loadJson(versionPath)) == null) {
if (fetchFromVersion) {
downloadVersion(true);
downloadAssets(false);
}
return;
}
JsonObject assetIndex = json.getAsJsonObject("assetIndex");
String assetUrl = assetIndex.get("url").getAsString();
fetchAndSave(assetUrl, assetsPath);
}
private static void downloadVersion(boolean fetchFromManifest) throws Exception {
JsonObject json;
if (!Files.exists(Path.of(manifestPath)) || (json = loadJson(manifestPath)) == null) {
if (fetchFromManifest) {
fetchAndSave(manifestUrl, manifestPath);
downloadVersion(false);
}
return;
}
String versionUrl = null;
for (JsonElement element : json.getAsJsonArray("versions")) {
String id = element.getAsJsonObject().get("id").getAsString();
String url = element.getAsJsonObject().get("url").getAsString();
if (VERSION.equals(id)) {
versionUrl = url;
break;
}
}
if (versionUrl == null) {
throw new RuntimeException("Could not find version URL");
}
fetchAndSave(versionUrl, versionPath);
}
private static String createHttpResponse(String path) throws IOException, InterruptedException {
try {
HttpResponse<String> response;
try (HttpClient httpClient = HttpClient.newHttpClient()) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(path))
.build();
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
int responseCode = response.statusCode();
if (responseCode != 200) {
logger.info("Unexpected response code: " + responseCode);
logger.info("Response body: " + response.body());
throw new UnsupportedEncodingException("Unexpected response code");
} else {
return response.body();
}
} catch (Exception e) {
logger.warning("Error in getting info: " + e.getMessage());
throw e;
}
}
private static byte[] fetch(String urlString) throws IOException, InterruptedException {
String ret = createHttpResponse(urlString);
return ret.getBytes();
}
private static void fetchAndSave(String url, String savePath) throws IOException, InterruptedException {
byte[] data = fetch(url);
Path outputPath = Path.of(savePath);
Files.createDirectories(outputPath.getParent());
Files.write(outputPath, data, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
}
private static void cleanCache() {
try {
FileUtils.deleteDirectory(Path.of(BASE_PATH).toFile());
} catch (IOException e) {
logger.severe("Cache cleanup failed: " + e);
}
}
private static JsonObject loadJson(String path) {
try {
byte[] data = Files.readAllBytes(Paths.get(path));
return JsonParser.parseString(new String(data)).getAsJsonObject();
} catch (JsonSyntaxException e) {
logger.warning("Corrupt json file: " + e);
throw e;
} catch (Exception e) {
logger.warning("Failed to load local JSON: " + e);
return null;
}
}
private static Language createLangInstance() throws IOException {
DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource();
Map<String, String> map = new HashMap<>();
parseTranslations(map::put);
deprecatedTranslationsInfo.applyToMap(map);
final Map<String, String> map1 = Map.copyOf(map);
return new Language() {
@Override
public @NotNull String getOrDefault(@NotNull String key, @NotNull String defaultValue) {
return map1.getOrDefault(key, defaultValue);
}
@Override
public boolean has(@NotNull String id) {
return map1.containsKey(id);
}
@Override
public boolean isDefaultRightToLeft() {
return false;
}
@Override
public @NotNull FormattedCharSequence getVisualOrder(@NotNull FormattedText text) {
return sink -> text.visit(
(style, content) -> StringDecomposer.iterateFormatted(content, style, sink) ? Optional.empty() : FormattedText.STOP_ITERATION,
Style.EMPTY
)
.isPresent();
}
};
}
private static void parseTranslations(BiConsumer<String, String> output) throws IOException {
Path filePath = Path.of(langPath);
try (InputStream fileStream = Files.newInputStream(filePath)) {
Language.loadFromJson(fileStream, output);
} catch (NoSuchFileException noSuchFileException) {
logger.warning("Couldn't find language file: " + langPath);
throw noSuchFileException;
} catch (Exception e) {
logger.warning("Failed to load language from filesystem " + filePath + "\n" + e);
throw e;
}
}
}
@@ -0,0 +1,78 @@
package fun.bm.lophine.utils;
import fun.bm.lophine.config.modules.misc.ContainerExpansionConfig;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.component.ItemContainerContents;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public class ShulkerBoxesUtil {
public static boolean shouldCheck() {
return ContainerExpansionConfig.shulkerCount > 1 && ContainerExpansionConfig.shulkerCount <= 64;
}
public static boolean checkShulkerBox(ItemStack itemStack) {
return shouldCheck() && checkIsShulkerBox(itemStack);
}
public static boolean checkIsShulkerBox(ItemStack itemStack) {
return itemStack.getItem() instanceof BlockItem b && b.getBlock() instanceof ShulkerBoxBlock;
}
public static int getItemMaxCount(ItemStack itemStack) {
if (checkShulkerBox(itemStack)) {
return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64);
}
return itemStack.getMaxStackSize();
}
public static int getShulkerBoxesMaxCountUnsafe() {
return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64);
}
public static boolean emptyShulkerBoxCheck(@NotNull ItemStack stack) {
return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty();
}
public static boolean isStackable(ItemStack itemStack) {
return getItemMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
}
public static int getItemStackMaxCountReal(ItemStack stack) {
CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
return nbt.getInt("Lophine.RealStackSize").orElse(stack.getMaxStackSize());
}
public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
int realMaxStackSize = getItemStackMaxCountReal(itemStack);
int modifiedMaxStackSize = getItemMaxCount(itemStack);
if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
nbt.putInt("Lophine.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("Lophine.RealStackSize");
if (nbt.isEmpty()) {
itemStack.remove(DataComponents.CUSTOM_DATA);
} else {
itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
}
}
return itemStack;
}
}
+13 -3
View File
@@ -8,11 +8,21 @@ project_id_b="Lophine"
commitid=$(git log --pretty='%h' -1)
mcversion=$(prop mcVersion)
grdversion=$(prop version)
preVersion=$(prop preVersion)
release=$(prop release)
release_tag="$mcversion-$commitid"
jarName="$project_id-$mcversion-paperclip.jar"
jarName_dir="lophine-server/build/libs/$jarName"
make_latest=$([ $preVersion = "true" ] && echo "false" || echo "true")
pre=false
make_latest=false
if [ "$release" = "1" ]; then
pre=true
make_latest=false
elif [ "$release" = "2" ]; then
pre=false
make_latest=true
fi
mv lophine-server/build/libs/$project_id-paperclip-$grdversion-mojmap.jar $jarName_dir
@@ -21,7 +31,7 @@ echo "project_id_b=$project_id_b" >> $GITHUB_ENV
echo "commit_id=$commitid" >> $GITHUB_ENV
echo "commit_msg=$(git log --pretty='> [%h] %s' -1)" >> $GITHUB_ENV
echo "mcversion=$mcversion" >> $GITHUB_ENV
echo "pre=$preVersion" >> $GITHUB_ENV
echo "pre=$pre" >> $GITHUB_ENV
echo "tag=$release_tag" >> $GITHUB_ENV
echo "jar=$jarName" >> $GITHUB_ENV
echo "jar_dir=$jarName_dir" >> $GITHUB_ENV
+1
View File
@@ -3,6 +3,7 @@ pluginManagement {
gradlePluginPortal()
mavenLocal()
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.menthamc.com/repository/maven-public/")
}
}