Compare commits

...

13 Commits

Author SHA1 Message Date
Helvetica Volubi 580201740e fix: update references and add additional launch parameters in documentation 2026-07-25 21:33:59 +08:00
Helvetica Volubi d54b248f27 fix: fix I18n in config comments 2026-07-25 19:45:01 +08:00
Helvetica Volubi 11b0b05a93 [ci skip]fix workflow & fix typo 2026-07-25 19:21:42 +08:00
Helvetica Volubi 7db058ef56 feat: add zh_cn config comment support & update en_us
Co-authored-by: flowingsun <rain_wyc@outlook.com>
2026-07-25 16:52:23 +08:00
Helvetica Volubi 019adaf46f fix: replace NullPlugin with MinecraftInternalPlugin in delayed task scheduling 2026-07-25 14:08:35 +08:00
Helvetica Volubi 6f55ed7e8e [ci skip]fix: update contribution guidelines for clarity on file submission 2026-07-25 13:17:02 +08:00
Helvetica Volubi 12c58f69b3 [ci skip]docs: add localized comment support instructions for configuration entries 2026-07-25 02:17:06 +08:00
Helvetica Volubi 0fd3b32108 fix: fix typo 2026-07-24 22:58:05 +08:00
Helvetica Volubi b8f43b47e6 resort comments in json 2026-07-24 22:16:25 +08:00
Helvetica Volubi 5f718d45a1 pre update for config comment I18n support 2026-07-24 20:34:55 +08:00
Helvetica Volubi 1cbb19d9e4 fix a losing api 2026-07-24 01:52:18 +08:00
Helvetica Volubi 4339b5e8a6 [ci skip] fix typo 2026-07-23 01:29:34 +08:00
Helvetica Volubi bcbc0685b2 [ci skip] update more information 2026-07-23 00:48:51 +08:00
140 changed files with 905 additions and 907 deletions
+3 -3
View File
@@ -3,11 +3,11 @@ Lophine inherits its licensing from the included upstream projects.
Lophine从上游继承了许可证。
As such, Lophine is licensed under the
[GNU General Public License version 3](licenses/GPL.md); as it inherits it from Luminol,
who in turn inherits it from the original Folia, Paper, Spigot, Bukkit and CraftBukkit projects.
[GNU General Public License version 3](licenses/GPL.md); as it inherits it from Folia,
who in turn inherits it from the original Paper, Spigot, Bukkit and CraftBukkit projects.
因此,Lophine中应当遵守[GNU通用公共许可证-第3版](licenses/GPL.md)
因为Lophine从上游Luminol继承了它,而Luminol又从其上游的Folia、Paper、Spigot、Bukkit和Craftbukkit项目中继承了它。
因为Lophine从上游Folia继承了它,而Folia又从其上游的Paper、Spigot、Bukkit和Craftbukkit项目中继承了它。
Any author who is _not_ listed below should be presumed to have released their work
under the original [GPL](licenses/GPL.md) license.
+8 -2
View File
@@ -3,7 +3,7 @@
# Lophine
*Lophine 是一个基于Luminol的分支,具有许多有用的优化和可配置的原版特性,目标是在Folia上实现更多生电的内容(请注意,完整生电请使用Fabric)*
*Lophine 是一个基于Folia的分支,具有许多有用的优化和可配置的原版特性,目标是在Folia上实现更多生电的内容(请注意,完整生电请使用Fabric)*
![Created At](https://img.shields.io/github/created-at/LophineLabs/Lophine?style=for-the-badge&color=blue)
[![License](https://img.shields.io/github/license/LophineLabs/Lophine?style=for-the-badge&color=green)](LICENSE.md)
@@ -29,6 +29,12 @@
- 🔬 **生电功能增强** - 在 Folia 上实现更多生电内容(完整生电请使用 Fabric)
- 🛠️ **更多实用功能** - 持续添加有用的服务器功能
### 额外启动参数
- morninggloryclip.useMojangSource 强制服务端使用mojang源下载文件
- morninggloryclip.enable.mixin 启用服务器插件的mixin支持
## 📥 下载
### 稳定版本
@@ -79,7 +85,7 @@ dependencies {
<dependencies>
<dependency>
<groupId>fun.bm.lophine</groupId>
<artifactId>luminol-api</artifactId>
<artifactId>lophine-api</artifactId>
<version>$VERSION</version>
</dependency>
</dependencies>
+7 -2
View File
@@ -3,7 +3,7 @@
# Lophine
*Lophine is a Luminol fork with many useful optimizations and configurable vanilla features, aims to provide more function for survival-usable circuit on folia (Please note that Fabric should be used for complete survival-usable)*
*Lophine is a Folia fork with many useful optimizations and configurable vanilla features, aims to provide more function for survival-usable circuit on folia (Please note that Fabric should be used for complete survival-usable)*
![Created At](https://img.shields.io/github/created-at/LophineLabs/Lophine?style=for-the-badge&color=blue)
[![License](https://img.shields.io/github/license/LophineLabs/Lophine?style=for-the-badge&color=green)](LICENSE.md)
@@ -29,6 +29,11 @@
- 🔬 **Redstone Enhancement** - More redstone functionality on Folia (use Fabric for complete redstone features)
- 🛠️ **More Useful Functions** - Continuously adding useful server features
### Additional Launch Parameters
- morninggloryclip.useMojangSource - Use Mojang's source for Minecraft Server
- morninggloryclip.enable.mixin - Enable mixin support for Leaves Plugin
## 📥 Download
### Stable Releases
@@ -79,7 +84,7 @@ dependencies {
<dependencies>
<dependency>
<groupId>fun.bm.lophine</groupId>
<artifactId>luminol-api</artifactId>
<artifactId>lophine-api</artifactId>
<version>$VERSION</version>
<scope>provided</scope>
</dependency>
+96
View File
@@ -1,3 +1,4 @@
import groovy.json.JsonSlurper
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
@@ -105,3 +106,98 @@ subprojects {
}
}
}
// Sort all JSON language files under the lang directory by key in ASCII order
val langDir = layout.projectDirectory.dir("lophine-server/src/main/resources/assets/lophine/lang")
tasks.register("sortLangKeys") {
group = "lophine"
description = "Sort all JSON language files by key in ASCII (ordinal) order"
notCompatibleWithConfigurationCache("Inline task action references build script class")
inputs.dir(langDir).optional()
outputs.dir(langDir)
doLast {
val dir = langDir.asFile
if (!dir.isDirectory) {
logger.warn("Lang directory not found: $dir")
return@doLast
}
val jsonFiles = dir.listFiles { f -> f.extension == "json" }?.sortedBy { it.name } ?: emptyList()
if (jsonFiles.isEmpty()) {
logger.lifecycle("No .json files found in: $dir")
return@doLast
}
val slurper = JsonSlurper()
for (file in jsonFiles) {
@Suppress("UNCHECKED_CAST")
val data = slurper.parse(file) as Map<String, Any?>
val sorted = data.toSortedMap()
val pretty = formatJson(sorted)
file.writeText(pretty + "\n", charset = Charsets.UTF_8)
logger.lifecycle("Processed: ${file.name} (${sorted.size} keys)")
}
logger.lifecycle("Done.")
}
}
// --- Pure-Kotlin JSON serializer that preserves non-ASCII characters (e.g. CJK) ---
fun formatJson(value: Any?, indent: Int = 2): String {
val sb = StringBuilder()
appendJson(sb, value, indent, 0)
return sb.toString()
}
private fun appendJson(sb: StringBuilder, value: Any?, indent: Int, level: Int) {
when (value) {
null -> sb.append("null")
is Boolean -> sb.append(value)
is Number -> sb.append(value)
is String -> sb.append('"').append(escapeJsonString(value)).append('"')
is List<*> -> {
if (value.isEmpty()) { sb.append("[]"); return }
sb.append("[\n")
value.forEachIndexed { i, v ->
sb.append(" ".repeat(indent * (level + 1)))
appendJson(sb, v, indent, level + 1)
if (i < value.size - 1) sb.append(',')
sb.append('\n')
}
sb.append(" ".repeat(indent * level)).append(']')
}
is Map<*, *> -> {
if (value.isEmpty()) { sb.append("{}"); return }
sb.append("{\n")
val entries = value.entries.toList()
entries.forEachIndexed { i, (k, v) ->
sb.append(" ".repeat(indent * (level + 1)))
sb.append('"').append(escapeJsonString(k.toString())).append('"')
sb.append(": ")
appendJson(sb, v, indent, level + 1)
if (i < entries.size - 1) sb.append(',')
sb.append('\n')
}
sb.append(" ".repeat(indent * level)).append('}')
}
else -> sb.append('"').append(escapeJsonString(value.toString())).append('"')
}
}
private fun escapeJsonString(s: String): String {
val sb = StringBuilder(s.length)
for (c in s) {
when (c) {
'"' -> sb.append("\\\"")
'\\' -> sb.append("\\\\")
'\b' -> sb.append("\\b")
'\u000C' -> sb.append("\\f")
'\n' -> sb.append("\\n")
'\r' -> sb.append("\\r")
'\t' -> sb.append("\\t")
else -> if (c.code < 0x20) {
sb.append("\\u").append(String.format("%04x", c.code))
} else {
sb.append(c) // preserve CJK and all other printable chars as-is
}
}
}
return sb.toString()
}
+13 -5
View File
@@ -21,7 +21,7 @@
在开始开发之前,您首先需要拥有以下软件作为开发环境:
- `git`
- `JDK 21 或更高版本`
- `JDK 25 或更高版本`
特别提醒:在操作前,您需要启用系统和Git的长路径支持,以下为部分平台的相关描述。
@@ -41,7 +41,7 @@ Lophine 使用和 Folia 一样的补丁系统,并为了针对不同部分的
1. 将你的仓库 clone 到本地;
2. 在你的 IDE 或 终端 内执行 Gradle 的 `applyAllPatches` 任务,如果是在终端内,你可以执行 `./gradlew applyAllPatches`
3. 在执行操作后,仓库根目录下应该存在以下目录对: `lophine-api``lophine-server` `luminol-api``luminol-server` `folia-api``folia-server` 以及 `paper-api``paper-server`(下文称作 `*-api``*-server` );
3. 在执行操作后,仓库根目录下应该存在以下目录对: `lophine-api``lophine-server` , `folia-api``folia-server` 以及 `paper-api``paper-server`(下文称作 `*-api``*-server` );
4. 进入 仓库根目录下的 `*-api``*-server` 文件夹进行修改。
以下为对上述各个文件夹的简单描述,详细描述可以参考[这里](https://github.com/Toffikk/paperweight-examples/blob/18241979c88068d5b061d95ad69c98ecb201c246/README.md)
@@ -49,14 +49,12 @@ Lophine 使用和 Folia 一样的补丁系统,并为了针对不同部分的
1. 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原版服务器的修改和新增文件应当在此文件夹下进行
- `luminol-server` :对luminol-server的修改应当在此文件夹下进行
- `folia-server` :对folia-Server的修改应当在此文件夹下进行
- `paper-server` :对于paper对服务器逻辑的修改应当在此文件夹下进行
@@ -64,7 +62,7 @@ Lophine 使用和 Folia 一样的补丁系统,并为了针对不同部分的
- 在应用补丁前,基点将会指向未被更改的源码
- 在基点后的每一个提交都是一个补丁
- 只有在 Luminol 最后一个提交后的提交才会被视为 lophine 补丁
- 只有在 Folia 最后一个提交后的提交才会被视为 lophine 补丁
## 增加补丁
@@ -90,3 +88,13 @@ Lophine 使用和 Folia 一样的补丁系统,并为了针对不同部分的
4. 运行 Gradle 任务 `fixupPaperApiFilePatches` 来修改已被修改的在lophine新建文件的补丁(注意不要提交);
5. 运行 Gradle 任务 `rebuildAllServerPatches` 来修改已被修改的补丁;
6. 将修改后的补丁 PR 发回储存库。
## 为配置项提供本地化的注释支持
1.`lophine-server/src/main/resources/assets/lophine/lang` 目录下创建或修改相应的语言文件,添加本地化的注释;
- 文件的名字应当符合 `https://minecraft.wiki/w/Language` 页面下的格式,如 `en_us` `zh_cn` `zh_hk` `zh_tw`,文件以 `json` 为格式类型;
2. 运行 Gradle 任务 `sortLangKeys` 来对你的语言文件内容进行重排序;
3. 使用 `git commit -m <提交信息>` 进行提交;
4. 将你修改的文件进行推送。
这样做以后,你就可以将你的修改进行 PR 提交。
+13 -5
View File
@@ -23,7 +23,7 @@ See also [This issue](https://github.com/isaacs/github/issues/1681), and then yo
Before coding, you need these pieces of software / tools as Dev Environment.
- `git`
- `JDK 21 or higher`
- `JDK 25 or higher`
PS: You need to enable long path support in your System and Git before start, some of the platform's resolution here.
@@ -44,7 +44,7 @@ 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` , `luminol-api` and `luminol-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` , `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):
@@ -52,14 +52,12 @@ The following is the simple description of the aforementioned folders, detailed
1. API part
- `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` : 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
@@ -67,7 +65,7 @@ BTW, `*-api` and `*-server` and are not normal git repositories.
- Before applying patches, the base will point to unmodified source code.
- Every commit after the base is a patch.
- Only commits after the last commit of Luminol will be considered as Lophine patches.
- Only commits after the last commit of Folia will be considered as Lophine patches.
## Adding new patches
@@ -93,3 +91,13 @@ You can modify an existing patch by following the steps below:
4. Run Gradle's task `fixupPaperApiFilePatches` to regenerate lophine-created files to patches (PS: do not commit again before you run this task)
5. Run Gradle's task `rebuildAllServerPatches` to modify existing patches
6. Push and PR again
## Providing localized comment support for configuration entries
1. Create or modify the corresponding language file under the `lophine-server/src/main/resources/assets/lophine/lang` directory to add localized comments;
- The file name should follow the format listed on the `https://minecraft.wiki/w/Language` page, such as `en_us`, `zh_cn`, `zh_hk`, `zh_tw`. The file format is `json`;
2. Run the Gradle task `sortLangKeys` to re-sort the keys in your language file;
3. Commit your changes using `git commit -m <Commit Message>`;
4. Push your modified files to your repository.
After pushing, you can open a PR to submit your changes.
+1 -1
View File
@@ -2,7 +2,7 @@ group=fun.bm.lophine
mcVersion=26.2
apiVersion=26.2
channel=STABLE
clipVersion=3.0.18
clipVersion=1.0.0
weightVersion=2.0.15
# true for release, false for skip release, pre for pre-release
release=pre
@@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java
index 652ff54e7c50412503725d628bfe72ed03059790..273bd3f354281c7ddbe2a3719be063b1d46e5445 100644
index 652ff54e7c50412503725d628bfe72ed03059790..1727ea0b873ee4f9a86cca62eac6dc3a5063b4e6 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfo.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java
@@ -19,6 +19,17 @@ public interface ServerBuildInfo {
@@ -5,16 +5,17 @@ Subject: [PATCH] Luminol Config System
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index fb5ca3ab0ddba433a39e65572beeb955b50d6f72..42335e351e0cb4f82f46501503a15349f8a82e1b 100644
index fb5ca3ab0ddba433a39e65572beeb955b50d6f72..a139182704a5f147661816d08907be8a7f8f7dde 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2776,6 +2776,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -2776,6 +2776,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
void allowPausing(@NotNull org.bukkit.plugin.Plugin plugin, boolean value);
// Paper end - API to check if the server is sleeping
+
+ // Luminol start - Luminol Config API
+ me.earthme.luminol.api.config.LuminolConfigsInstance getLuminolConfigs(String name);
+ me.earthme.luminol.api.config.LuminolConfigBuilder getLuminolConfigBuilder();
+ // Luminol end - Luminol Config API
+
// Folia start - region TPS API
@@ -23,11 +23,11 @@ index 8a24b84db656da4cec59e9bccac306467c8155b0..0ac1e049fad85de8365380b03e60d915
+ // Leaves end - Feature API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 42335e351e0cb4f82f46501503a15349f8a82e1b..cd5f47f6d7fa15c1533724673b8bc2c75394795b 100644
index a139182704a5f147661816d08907be8a7f8f7dde..a8c262064e4058f786c62c333130c4cac0ce4b66 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2781,6 +2781,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
me.earthme.luminol.api.config.LuminolConfigsInstance getLuminolConfigs(String name);
@@ -2782,6 +2782,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
me.earthme.luminol.api.config.LuminolConfigBuilder getLuminolConfigBuilder();
// Luminol end - Luminol Config API
+ // Leaves start - Feature API
@@ -5,7 +5,7 @@ Subject: [PATCH] World load/unload APIs
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index cd5f47f6d7fa15c1533724673b8bc2c75394795b..48e53223ba7edeca5256244480441a56a6657075 100644
index a8c262064e4058f786c62c333130c4cac0ce4b66..3c92440fbef6e6970cd800e0038a625a775eda9a 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -775,6 +775,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -28,10 +28,10 @@ index 0ac1e049fad85de8365380b03e60d915ee643f16..a747fbe107dcc134558ca8ecfbe30e81
+ // Leaves end - Bot API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 48e53223ba7edeca5256244480441a56a6657075..f4f64538d13f3dba5a1cd8f0d24d1fd2e8b75749 100644
index 3c92440fbef6e6970cd800e0038a625a775eda9a..c8fc95a85b162cc71aa8dada8f87f4fe6f5dad12 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2826,4 +2826,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -2827,4 +2827,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
double @Nullable [] getRegionTPS(@NotNull World world, int chunkX, int chunkZ);
// Folia end - region TPS API
@@ -23,10 +23,10 @@ index a747fbe107dcc134558ca8ecfbe30e81245a5742..b09a90f8187a15ddaa15f231f46f51f2
+ // Leaves end - Photographer API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index f4f64538d13f3dba5a1cd8f0d24d1fd2e8b75749..2f4cc1115170557389f577f995f1bfaed1ec2f71 100644
index c8fc95a85b162cc71aa8dada8f87f4fe6f5dad12..5e4da280f7bed1084ebc2814d23901ad072e116d 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2835,4 +2835,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
@@ -2836,4 +2836,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
@NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager();
// Leaves end - Bot API
+2 -2
View File
@@ -15,7 +15,7 @@
dependencies {
mache("io.papermc:mache:26.2+build.1")
- paperclip("io.papermc:paperclip:3.0.4")
+ hyacinthusclip("moe.luminolmc:hyacinthusclip:${providers.gradleProperty("clipVersion").get()}") // TODO Later - rebrand
+ hyacinthusclip("fun.bm:morninggloryclip:${providers.gradleProperty("clipVersion").get()}") // TODO Later - rebrand
}
paperweight {
@@ -128,7 +128,7 @@
"Build-Number" to (build ?: ""),
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
@@ -213,6 +_,20 @@
@@ -214,6 +_,20 @@
}
}
}
@@ -3,10 +3,10 @@ From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 5 Jun 2026 15:09:29 +0800
Subject: [PATCH] Add config to enable tick command
only freeze/unfreeze/step/query can run when enabled
only freeze/unfreeze/step/query/rate can run when enabled
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index ff90abb47203c03636d3175f2b3efcf43517b3b0..276349d778c2e6f0b1081eec4851bad5d25db237 100644
index ff90abb47203c03636d3175f2b3efcf43517b3b0..a2db29aa47a4b7213d4956f02f6e83122ccfdbd1 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -239,6 +239,11 @@ public final class RegionizedServer {
@@ -21,7 +21,22 @@ index ff90abb47203c03636d3175f2b3efcf43517b3b0..276349d778c2e6f0b1081eec4851bad5
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -415,7 +420,7 @@ public final class RegionizedServer {
@@ -265,6 +270,14 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Lophine start - Add a config to enable tick command
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ rateManager.reduceSprintTicks();
+ rateManager.endTickWork();
+ }
+ // Lophine end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
@@ -415,7 +428,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final long tickCount) {
@@ -31,10 +46,48 @@ index ff90abb47203c03636d3175f2b3efcf43517b3b0..276349d778c2e6f0b1081eec4851bad5
}
}
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..5f4f80c1d4003254fd840f71d86908603b57bfa2 100644
index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..57a35d7a801621fc461e896eb2bba533d9d5bc1b 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -559,6 +559,11 @@ public final class TickRegionScheduler {
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Lophine - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Lophine - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -509,8 +509,24 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Lophine start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ if (rateManager.isSprinting() && rateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = rateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Lophine end - Add a config to enable tick command
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
@@ -559,6 +575,11 @@ public final class TickRegionScheduler {
try {
// next start isn't updated until the end of this tick
this.tickRegion(tickCount, tickStart, scheduledEnd);
@@ -63,27 +116,54 @@ index 6823c41c08ca1a1baf9257fc861ae97bbcbe3a50..0fa14f60310b063f419620539fd40898
TimeCommand.register(this.dispatcher, context);
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index eeb2f88723b37bb3cada04bf3098dd46f0ed7316..8432d0ce22ddc9c9bfa98901e403697f40e53c99 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Lophine start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Lophine end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index e8d6a67143f3f0b4813e51bb273498bc404899b9..64b685b219b930a1bb7f85db9947f4d1ca9df093 100644
index e8d6a67143f3f0b4813e51bb273498bc404899b9..4421658e4061299dea2ff72a77506214cc9045d8 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -23,14 +23,14 @@ public class TickCommand {
@@ -15,7 +15,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Lophine - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -23,7 +23,7 @@ public class TickCommand {
Commands.literal("tick")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
- .then(
+/* .then(
+ .then( // Lophine - Add tick rate support
Commands.literal("rate")
.then(
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
)
- )
+ )*/
.then(
Commands.literal("step")
.executes(c -> step(c.getSource(), 1))
@@ -41,7 +41,7 @@ public class TickCommand {
.executes(c -> step(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
)
@@ -5,7 +5,7 @@ Subject: [PATCH] Server I18n
diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java
index 47cd33bce908744e64356b585853d6a8ecf82443..bb4011d3c6a1d2a5aa66e68fe719cd5eea2c0dd2 100644
index 47cd33bce908744e64356b585853d6a8ecf82443..9e6f89ac7cf730bfc3c15d5a4f648c550cf72e22 100644
--- a/net/minecraft/locale/Language.java
+++ b/net/minecraft/locale/Language.java
@@ -37,6 +37,7 @@ public abstract class Language {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable save-all command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 276349d778c2e6f0b1081eec4851bad5d25db237..79ef1e69ec364beec69b37c6850c038cdba73b4c 100644
index a2db29aa47a4b7213d4956f02f6e83122ccfdbd1..6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -265,6 +265,8 @@ public final class RegionizedServer {
@@ -1,123 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 21 Jan 2026 21:28:21 +0800
Subject: [PATCH] Add tick rate support
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 79ef1e69ec364beec69b37c6850c038cdba73b4c..6fb3c88463ff69bddb7d8dcde0e5339567d3e1c6 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -272,6 +272,14 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
+ // Lophine start - Add a config to enable tick command
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ rateManager.reduceSprintTicks();
+ rateManager.endTickWork();
+ }
+ // Lophine end - Add a config to enable tick command
+
// tick connections
this.tickConnections();
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
index 5f4f80c1d4003254fd840f71d86908603b57bfa2..57a35d7a801621fc461e896eb2bba533d9d5bc1b 100644
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
@@ -40,8 +40,8 @@ public final class TickRegionScheduler {
}
}
- public static final int TICK_RATE = 20;
- public static final long TIME_BETWEEN_TICKS = 1_000_000_000L / TICK_RATE; // ns
+ public static float TICK_RATE = 20; // Lophine - Add tick command support
+ public static long TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); // ns // Lophine - Add tick command support
// Folia start - watchdog
public static final FoliaWatchdogThread WATCHDOG_THREAD = new FoliaWatchdogThread();
static {
@@ -509,8 +509,24 @@ public final class TickRegionScheduler {
final long cpuStart = MEASURE_CPU_TIME ? THREAD_MX_BEAN.getCurrentThreadCpuTime() : 0L;
final long tickStart = System.nanoTime();
- // use max(), don't assume that tickStart >= scheduledStart
- final long tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ // Lophine start - Add a config to enable tick command
+ final long tickCount;
+ if (fun.bm.lophine.carpet.config.modules.GeneralCompatConfig.commandTick) {
+ net.minecraft.server.ServerTickRateManager rateManager = MinecraftServer.getServer().tickRateManager();
+ if (rateManager.isSprinting() && rateManager.checkShouldSprintThisTick()) {
+ TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE;
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = 1;
+ } else {
+ TICK_RATE = rateManager.tickrate();
+ TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE);
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ } else {
+ // use max(), don't assume that tickStart >= scheduledStart
+ tickCount = Math.max(1L, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart));
+ }
+ // Lophine end - Add a config to enable tick command
if (!this.tryMarkTicking()) {
if (!this.cancelled.get()) {
diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java
index eeb2f88723b37bb3cada04bf3098dd46f0ed7316..8432d0ce22ddc9c9bfa98901e403697f40e53c99 100644
--- a/net/minecraft/server/ServerTickRateManager.java
+++ b/net/minecraft/server/ServerTickRateManager.java
@@ -110,7 +110,7 @@ public class ServerTickRateManager extends TickRateManager {
return false;
} else if (this.remainingSprintTicks > 0L) {
this.sprintTickStartTime = System.nanoTime();
- this.remainingSprintTicks--;
+ // this.remainingSprintTicks--; // Luminol - Add tick command support
return true;
} else {
this.finishTickSprint();
@@ -118,6 +118,12 @@ public class ServerTickRateManager extends TickRateManager {
}
}
+ // Lophine start - Add tick command support
+ public void reduceSprintTicks() {
+ this.remainingSprintTicks--;
+ }
+ // Lophine end - Add tick command support
+
public void endTickWork() {
this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime);
}
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
index 64b685b219b930a1bb7f85db9947f4d1ca9df093..4421658e4061299dea2ff72a77506214cc9045d8 100644
--- a/net/minecraft/server/commands/TickCommand.java
+++ b/net/minecraft/server/commands/TickCommand.java
@@ -15,7 +15,7 @@ import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.TimeUtil;
public class TickCommand {
- private static final float MAX_TICKRATE = 10000.0F;
+ public static final float MAX_TICKRATE = 10000.0F; // Lophine - Add tick command support
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(final CommandDispatcher<CommandSourceStack> dispatcher) {
@@ -23,14 +23,14 @@ public class TickCommand {
Commands.literal("tick")
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
-/* .then(
+ .then( // Lophine - Add tick rate support
Commands.literal("rate")
.then(
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
)
- )*/
+ )
.then(
Commands.literal("step")
.executes(c -> step(c.getSource(), 1))
@@ -11,58 +11,39 @@ import org.leavesmc.leaves.command.bot.BotCommand;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "fakeplayer",
directory = {"carpet"},
comments = """
Carpet fakeplayer compatibility mapped onto Lophine fakeplayers.
commandPlayer is currently backed by Lophine's /bot command surface."""
)
@ConfigClassInfo(category = EnumConfigCategory.ROOT, name = "fakeplayer", directory = {"carpet"})
public class FakePlayerCompatConfig implements IConfigModule {
@ConfigInfo(name = "commandPlayer", comments = """
Enable /player command.(not remapped)
If you want to enable bot command, please see lophine global config.""")
@ConfigInfo(name = "commandPlayer")
public static boolean commandPlayer = false;
@ConfigInfo(name = "fakePlayerResident", comments = """
Keep fakeplayers resident across unload and restart.""")
@ConfigInfo(name = "fakePlayerResident")
public static boolean fakePlayerResident = false;
@ConfigInfo(name = "openFakePlayerInventory", comments = """
Allow opening fakeplayer inventories.""")
@ConfigInfo(name = "openFakePlayerInventory")
public static boolean openFakePlayerInventory = false;
@ConfigInfo(name = "fakePlayerTicksLikeRealPlayer", comments = """
Tick fakeplayers in the network phase to better match real player timing.""")
@ConfigInfo(name = "fakePlayerTicksLikeRealPlayer")
public static boolean fakePlayerTicksLikeRealPlayer = false;
@ConfigInfo(name = "fakePlayerDefaultSurvivalMode", comments = """
Force newly created fakeplayers to start in survival instead of the server default gamemode.""")
@ConfigInfo(name = "fakePlayerDefaultSurvivalMode")
public static boolean fakePlayerDefaultSurvivalMode = false;
@ConfigInfo(name = "fakePlayerInteractLikeClient", comments = """
Make fakeplayer entity interaction follow client-side fallback behavior more closely.""")
@ConfigInfo(name = "fakePlayerInteractLikeClient")
public static boolean fakePlayerInteractLikeClient = false;
@ConfigInfo(name = "fakePlayerAutoReplaceTool", comments = """
Toggle automatic tool replacement for fakeplayers.""")
@ConfigInfo(name = "fakePlayerAutoReplaceTool")
public static boolean fakePlayerAutoReplaceTool = false;
@ConfigInfo(name = "fakePlayerAutoReplenishment", comments = """
Toggle automatic stack replenishment for fakeplayers.""")
@ConfigInfo(name = "fakePlayerAutoReplenishment")
public static boolean fakePlayerAutoReplenishment = false;
@ConfigInfo(name = "fakePlayerAutoReplenishmentFormShulkerBox", comments = """
Let fakeplayer replenishment pull matching items out of shulker boxes in the inventory.""")
@ConfigInfo(name = "fakePlayerAutoReplenishmentFormShulkerBox")
public static boolean fakePlayerAutoReplenishmentFormShulkerBox = false;
@ConfigInfo(name = "fakePlayerAutoFish", comments = """
Let fakeplayers holding a fishing rod automatically cast and reel it in.""")
@ConfigInfo(name = "fakePlayerAutoFish")
public static boolean fakePlayerAutoFish = false;
@ConfigInfo(name = "fakePlayerReloadAction", comments = """
Persist queued fakeplayer actions across save and reload.""")
@ConfigInfo(name = "fakePlayerReloadAction")
public static boolean fakePlayerReloadAction = false;
@DoNotLoad
@@ -8,248 +8,174 @@ import me.earthme.luminol.enums.EnumConfigCategory;
import java.util.List;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "general",
directory = {"carpet"},
comments = """
Carpet/AMS/TIS/Org compatibility rules backed by existing Lophine features.
Only rules that already have a working server-side implementation are exposed here."""
)
@ConfigClassInfo(category = EnumConfigCategory.ROOT, name = "general", directory = {"carpet"})
public class GeneralCompatConfig implements IConfigModule {
@ConfigInfo(name = "language", comments = """
Carpet language value.
ATTENTION: This config will not update in Lophine global now!""")
@ConfigInfo(name = "language")
public static String language = "en_us";
@ConfigInfo(name = "amsUpdateSuppressionCrashFix", comments = """
Update suppression crash protection.""")
@ConfigInfo(name = "amsUpdateSuppressionCrashFix")
public static boolean amsUpdateSuppressionCrashFix = false;
@ConfigInfo(name = "yeetUpdateSuppressionCrash", comments = """
Update suppression crash yeeting.""")
@ConfigInfo(name = "yeetUpdateSuppressionCrash")
public static boolean yeetUpdateSuppressionCrash = false;
@ConfigInfo(name = "dustTrapdoorReintroduced", comments = """
Should the pre-1.20 mechanism be reintroduced:
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters,
and redstone comparators do not check for attachment when receiving status updates from below.""")
@ConfigInfo(name = "dustTrapdoorReintroduced")
public static boolean dustTrapdoorReintroduced = false;
@ConfigInfo(name = "shulkerBoxCCEReintroduced", comments = """
Use ClassCastException for update suppression.""")
@ConfigInfo(name = "shulkerBoxCCEReintroduced")
public static boolean shulkerBoxCCEReintroduced = false;
@ConfigInfo(name = "instantBlockUpdaterReintroduced", comments = """
Instant block updater.""")
@ConfigInfo(name = "instantBlockUpdaterReintroduced")
public static boolean instantBlockUpdaterReintroduced = false;
@ConfigInfo(name = "commandTick", comments = """
Enable the tick command support.""")
@ConfigInfo(name = "commandTick")
public static boolean commandTick = false;
@ConfigInfo(name = "creativeNoClip", comments = """
Whether to enable creative fly no clip.
When enabled, players in creative mode will not collide with blocks while flying.
This allows them to pass through blocks without obstruction.""")
@ConfigInfo(name = "creativeNoClip")
public static boolean creativeNoClip = false;
@ConfigInfo(name = "optimizedDragonRespawn", comments = """
Enable optimized dragon respawn.""")
@ConfigInfo(name = "optimizedDragonRespawn")
public static boolean optimizedDragonRespawn = false;
@ConfigInfo(name = "antiSpamDisabled", comments = """
Disable the server-side chat and creative-drop spam throttles used by vanilla/Spigot.""")
@ConfigInfo(name = "antiSpamDisabled")
public static boolean antiSpamDisabled = false;
@ConfigInfo(name = "blockPlacementIgnoreEntity", comments = """
Allow creative players to place blocks without entity collision checks.""")
@ConfigInfo(name = "blockPlacementIgnoreEntity")
public static boolean blockPlacementIgnoreEntity = false;
@ConfigInfo(name = "creativeOpenContainerForcibly", comments = """
Allow creative players to forcibly open blocked chests, ender chests and shulker boxes.""")
@ConfigInfo(name = "creativeOpenContainerForcibly")
public static boolean creativeOpenContainerForcibly = false;
@ConfigInfo(name = "creativeOneHitKill", comments = """
Allow creative players to instantly kill attackable non-creative, non-spectator entities.
Sneaking expands the effect into a small area attack.""")
@ConfigInfo(name = "creativeOneHitKill")
public static boolean creativeOneHitKill = false;
@ConfigInfo(name = "observerNoDetection", comments = """
Disable observer detection pulses entirely.""")
@ConfigInfo(name = "observerNoDetection")
public static boolean observerNoDetection = false;
@ConfigInfo(name = "bambooModelNoOffset", comments = """
Remove the random horizontal model offset from bamboo and bamboo saplings.""")
@ConfigInfo(name = "bambooModelNoOffset")
public static boolean bambooModelNoOffset = false;
@ConfigInfo(name = "creativeNoItemCooldown", comments = """
Skip item cooldown application for creative players.""")
@ConfigInfo(name = "creativeNoItemCooldown")
public static boolean creativeNoItemCooldown = false;
@ConfigInfo(name = "ctrlQCraftingFix", comments = """
Compatibility flag for the upstream result-slot Ctrl+Q crafting fix already present in the current menu code.""")
@ConfigInfo(name = "ctrlQCraftingFix")
public static boolean ctrlQCraftingFix = false;
@ConfigInfo(name = "carpetAlwaysSetDefault", comments = """
Compatibility flag for Lophine's config loader, which already writes default values into the compat config during preload.""")
@ConfigInfo(name = "carpetAlwaysSetDefault")
public static boolean carpetAlwaysSetDefault = false;
@ConfigInfo(name = "placementRotationFix", comments = """
Use the player's main body rotation for placement direction checks instead of interpolated head yaw.""")
@ConfigInfo(name = "placementRotationFix")
public static boolean placementRotationFix = false;
@ConfigInfo(name = "tntDoNotUpdate", comments = """
Prevent TNT from checking redstone power when first placed.""")
@ConfigInfo(name = "tntDoNotUpdate")
public static boolean tntDoNotUpdate = false;
@ConfigInfo(name = "totallyNoBlockUpdate", comments = """
Suppress neighbor and shape updates globally for block changes.""")
@ConfigInfo(name = "totallyNoBlockUpdate")
public static boolean totallyNoBlockUpdate = false;
@ConfigInfo(name = "tiscmNetworkProtocol", comments = """
Enable the native Carpet TIS Addition network channel on `tiscm:network/v1`.""")
@ConfigInfo(name = "tiscmNetworkProtocol")
public static boolean tiscmNetworkProtocol = false;
@ConfigInfo(name = "hopperNoItemCost", comments = """
Restore the transferred stack into a hopper when a wool block is placed on top of it.""")
@ConfigInfo(name = "hopperNoItemCost")
public static boolean hopperNoItemCost = false;
@ConfigInfo(name = "explosionNoBlockDamage", comments = """
Let explosions damage entities without breaking blocks.""")
@ConfigInfo(name = "explosionNoBlockDamage")
public static boolean explosionNoBlockDamage = false;
@ConfigInfo(name = "noCreeperBlockBreaking", comments = """
Disables creeper explosion block breaking.""")
@ConfigInfo(name = "noCreeperBlockBreaking")
public static boolean noCreeperBlockBreaking = false;
@ConfigInfo(name = "noGhastBlockBreaking", comments = """
Disables ghast fireball explosion block breaking.""")
@ConfigInfo(name = "noGhastBlockBreaking")
public static boolean noGhastBlockBreaking = false;
@ConfigInfo(name = "disableBlazeFire", comments = """
Disables fire made from blaze fireballs.""")
@ConfigInfo(name = "disableBlazeFire")
public static boolean disableBlazeFire = false;
@ConfigInfo(name = "disableGhastFire", comments = """
Disables fire made from ghast fireballs.""")
@ConfigInfo(name = "disableGhastFire")
public static boolean disableGhastFire = false;
@ConfigInfo(name = "optimizedTNTHighPriority", comments = """
Compatibility flag for the already optimized server explosion path carried by the current runtime.""")
@ConfigInfo(name = "optimizedTNTHighPriority")
public static boolean optimizedTNTHighPriority = false;
@ConfigInfo(name = "tntPrimerMomentumRemoved", comments = """
Remove the random horizontal launch momentum from newly primed TNT.""")
@ConfigInfo(name = "tntPrimerMomentumRemoved")
public static boolean tntPrimerMomentumRemoved = false;
@ConfigInfo(name = "tntIgnoreRedstoneSignal", comments = """
Ignore redstone power when deciding whether TNT should auto-prime.""")
@ConfigInfo(name = "tntIgnoreRedstoneSignal")
public static boolean tntIgnoreRedstoneSignal = false;
@ConfigInfo(name = "tntDupingFix", comments = """
Toggle the piston desync path used by vanilla TNT duplication setups.""")
@ConfigInfo(name = "tntDupingFix")
public static boolean tntDupingFix = false;
@ConfigInfo(name = "interactionUpdates", comments = """
Control whether player interaction block changes emit normal block updates.
Set to false to suppress neighbor and shape updates during block use and breaking.""")
@ConfigInfo(name = "interactionUpdates")
public static boolean interactionUpdates = true;
@ConfigInfo(name = "xpNoCooldown", comments = """
Allow players to absorb multiple experience orbs in the same tick without pickup delay.""")
@ConfigInfo(name = "xpNoCooldown")
public static boolean xpNoCooldown = false;
@ConfigInfo(name = "powerfulExpMending", comments = """
Let picked-up experience repair all damaged mending items in the player's inventory, not only equipped gear.""")
@ConfigInfo(name = "powerfulExpMending")
public static boolean powerfulExpMending = false;
@ConfigInfo(name = "clientSettingsLostOnRespawnFix", comments = """
Reapply the player's last known client settings after respawn.""")
@ConfigInfo(name = "clientSettingsLostOnRespawnFix")
public static boolean clientSettingsLostOnRespawnFix = false;
@ConfigInfo(name = "sensibleEnderman", comments = """
Restrict enderman block pickup to pumpkins and melons only.""")
@ConfigInfo(name = "sensibleEnderman")
public static boolean sensibleEnderman = false;
@ConfigInfo(name = "entityInstantDeathRemoval", comments = """
Remove the normal 20gt delay before dead living entities are discarded.""")
@ConfigInfo(name = "entityInstantDeathRemoval")
public static boolean entityInstantDeathRemoval = false;
@ConfigInfo(name = "farmlandTrampledDisabled", comments = """
Prevent farmland from turning into dirt when entities land on it.""")
@ConfigInfo(name = "farmlandTrampledDisabled")
public static boolean farmlandTrampledDisabled = false;
@ConfigInfo(name = "shulkerGolem", comments = """
Allow a carved pumpkin on top of a shulker box to summon a shulker.""")
@ConfigInfo(name = "shulkerGolem")
public static boolean shulkerGolem = false;
@ConfigInfo(name = "preventEndSpikeRespawn", comments = """
Skip obsidian spike regeneration during dragon respawn.""")
@ConfigInfo(name = "preventEndSpikeRespawn")
public static boolean preventEndSpikeRespawn = false;
@ConfigInfo(name = "yeetOutOfOrderChatKick", comments = """
Ignore out-of-order secure chat chain checks instead of invalidating the chat session.""")
@ConfigInfo(name = "yeetOutOfOrderChatKick")
public static boolean yeetOutOfOrderChatKick = false;
@ConfigInfo(name = "betterCraftableBoneBlock", comments = """
Add the AMS alternate bone block recipe that yields 3 bone blocks from 9 bones.""")
@ConfigInfo(name = "betterCraftableBoneBlock")
public static boolean betterCraftableBoneBlock = false;
@ConfigInfo(name = "betterCraftableDispenser", comments = """
Add the AMS alternate dispenser recipes using a dropper.""")
@ConfigInfo(name = "betterCraftableDispenser")
public static boolean betterCraftableDispenser = false;
@ConfigInfo(name = "viewDistance", comments = """
Override the dedicated server's startup view distance with the Carpet-compatible value.""")
@ConfigInfo(name = "viewDistance")
public static int viewDistance = 12;
@ConfigInfo(name = "tickCommandPermission", comments = """
Override the `/tick` command permission level.
Accepts values in the range 0..4, where 2 matches old Carpet behavior and 3 keeps vanilla.""")
@ConfigInfo(name = "tickCommandPermission")
public static int tickCommandPermission = 3;
@ConfigInfo(name = "tickFreezeCommandToggleable", comments = """
Make `/tick freeze` toggle back to running when executed while the server is already frozen.""")
@ConfigInfo(name = "tickFreezeCommandToggleable")
public static boolean tickFreezeCommandToggleable = false;
@ConfigInfo(name = "syncServerMsptMetricsData", comments = """
Broadcast live MSPT samples through the native TISCM protocol channel.""")
@ConfigInfo(name = "syncServerMsptMetricsData")
public static boolean syncServerMsptMetricsData = false;
@ConfigInfo(name = "simpleInGameCalculator", comments = """
Evaluate chat messages prefixed with `=` as a simple calculator expression and reply privately.""")
@ConfigInfo(name = "simpleInGameCalculator")
public static boolean simpleInGameCalculator = false;
@ConfigInfo(name = "microTiming", comments = """
Compatibility flag for the built-in region profiler and timing instrumentation carried by Folia/Moonrise.""")
@ConfigInfo(name = "microTiming")
public static boolean microTiming = false;
@ConfigInfo(name = "fastRedstoneDust", comments = """
Route redstone dust updates through the Alternate Current fast-update backend.""")
@ConfigInfo(name = "fastRedstoneDust")
public static boolean fastRedstoneDust = false;
@ConfigInfo(name = "lagFreeSpawning", comments = """
Use the lightweight collision and precooked-mob spawning path for natural spawning checks.""")
@ConfigInfo(name = "lagFreeSpawning")
public static boolean lagFreeSpawning = false;
@ConfigInfo(name = "optimizedFastEntityMovement", comments = """
Compatibility flag for the always-on Moonrise/Paper fast entity movement collision pipeline.""")
@ConfigInfo(name = "optimizedFastEntityMovement")
public static boolean optimizedFastEntityMovement = false;
@ConfigInfo(name = "optimizedHardHitBoxEntityCollision", comments = """
Compatibility flag for the always-on Moonrise/Paper hard-hitbox entity collision optimizations.""")
@ConfigInfo(name = "optimizedHardHitBoxEntityCollision")
public static boolean optimizedHardHitBoxEntityCollision = false;
@ConfigInfo(name = "tntFuseDuration", comments = """
Override the default primed TNT fuse duration in ticks.
Accepts values in the range 0..32767.""")
@ConfigInfo(name = "tntFuseDuration")
public static int tntFuseDuration = 80;
@ConfigInfo(name = "defaultLoggers", comments = """
Carpet-style default logger subscriptions for players.
Examples: ["tps", "mob_caps", "counter white"]""")
@ConfigInfo(name = "defaultLoggers")
public static List<String> defaultLoggers = List.of();
public static boolean mergedUpdateSuppressionCrashEnabled() {
@@ -7,8 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@ConfigInfo(name = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
@ConfigInfo(name = "removed")
public static boolean enabled = true;
}
@@ -11,21 +11,12 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(
category = EnumConfigCategory.ROOT,
name = "hopper_counter",
directory = {"carpet"},
comments = """
Hopper counter functions."""
)
@ConfigClassInfo(category = EnumConfigCategory.ROOT, name = "hopper_counter", directory = {"carpet"})
public class WoolHopperCounterConfig implements IConfigModule {
@ConfigInfo(name = "hopperCounters", comments = """
Enable the existing wool hopper counter implementation.""")
@ConfigInfo(name = "hopperCounters")
public static boolean hopperCounters = false;
@ConfigInfo(name = "hopperCountersUnlimitedSpeed", comments = """
Remove the hopper transfer speed limit for counters.
Only effective when hopperCounters is enabled.""")
@ConfigInfo(name = "hopperCountersUnlimitedSpeed")
public static boolean hopperCountersUnlimitedSpeed = false;
@DoNotLoad
@@ -7,32 +7,21 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "command")
public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "trigger_command_enabled", comments =
"""
Allow to use trigger command""")
@ConfigInfo(name = "trigger_command_enabled")
public static boolean trigger = false;
@ConfigInfo(name = "function_command_enabled", comments =
"""
Allow to use function command""")
@ConfigInfo(name = "function_command_enabled")
public static boolean function = false;
@ConfigInfo(name = "scoreboard_command_enabled", comments =
"""
Allow to use scoreboard command""")
@ConfigInfo(name = "scoreboard_command_enabled")
public static boolean scoreboard = false;
@ConfigInfo(name = "enabled", directory = {"save_all_command"}, comments =
"""
Allow to use save-all command""")
@ConfigInfo(name = "enabled", directory = {"save_all_command"})
public static boolean saveAll = false;
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"}, comments =
"""
Log all process of save-all command to console""")
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"})
public static boolean logAllProcess = false;
@ConfigInfo(name = "save_all_command_timeout", directory = {"save_all_command"}, comments = """
Maximum seconds to save before the chunk report it is timeout.""")
@ConfigInfo(name = "save_all_command_timeout", directory = {"save_all_command"})
public static long saveAllTimeout = 30;
}
@@ -7,8 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "entity_damage_source_trace")
public class EntityDamageSourceTraceConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments =
"""
Allow trace damage source cross different Region Scheduler.""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -13,13 +13,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(name = "global_entities_counter", category = EnumConfigCategory.EXPERIMENT)
public class GlobalEntitiesCounter implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "version", comments = """
DISABLED
DEFAULT_SYNC: Enable global entities counter origin version with sync counter module.
DEFAULT_ASYNC: Enable global entities counter origin version with async counter module.
PRECISE: Enable precise mob cap calculation with incremental counting. Replaces the periodic full-scan with event-driven real-time updates.
You need to set per-player-mob-spawns to false on paper-world-defaults.yml or paper-world.yml""")
@ConfigInfo(name = "version")
public static GlobalEntitiesCounterType type = GlobalEntitiesCounterType.DISABLED;
@DoNotLoad
@@ -7,7 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "update-suppression-crash-fix")
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Should crash caused by update suppression be prevented?""")
@ConfigInfo(name = "enabled")
public static boolean enabled = true;
}
@@ -7,7 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "vanilla-like-experience")
public class VanillaLikeExperienceConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Restore a more vanilla-like technical gameplay experience by bypassing some Paper safety and behavior changes.""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -11,22 +11,16 @@ import me.earthme.luminol.enums.EnumConfigCategory;
public class ContainerExpansionConfig implements IConfigModule {
@HotReloadUnsupported
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "barrel_rows", comments =
"""
range: 1~6""")
@ConfigInfo(name = "barrel_rows")
public static int barrelRows = 3;
@HotReloadUnsupported
@CommandSuggestions(suggest = {"1", "2", "3", "4", "5", "6"})
@ConfigInfo(name = "enderchest_rows", comments =
"""
range: 1~6""")
@ConfigInfo(name = "enderchest_rows")
public static int enderchestRows = 3;
@CommandSuggestions(suggest = {"1", "2", "32", "64"})
@ConfigInfo(name = "shulker_stackable_count", directory = {"shulker_box"}, comments =
"""
range: 1~64""")
@ConfigInfo(name = "shulker_stackable_count", directory = {"shulker_box"})
public static int shulkerCount = 1;
@ConfigInfo(name = "same_nbt_shulker_stackable", directory = {"shulker_box"})
@@ -16,69 +16,52 @@ import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "fakeplayer")
public class FakeplayerConfig implements IConfigModule {
@ConfigInfo(name = "enable", comments = """
Enable fakeplayer functionality (/bot command)""")
@ConfigInfo(name = "enable")
public static boolean enable = true;
@ConfigInfo(name = "unable-fakeplayer-names", comments = """
List of names that cannot be used for fakeplayers""")
@ConfigInfo(name = "unable-fakeplayer-names")
public static List<String> unableNames = List.of("player-name");
@ConfigInfo(name = "limit", comments = """
Maximum number of fakeplayers allowed""")
@ConfigInfo(name = "limit")
public static int limit = 10;
@ConfigInfo(name = "prefix", comments = """
Prefix for fakeplayer names""")
@ConfigInfo(name = "prefix")
public static String prefix = "";
@ConfigInfo(name = "suffix", comments = """
Suffix for fakeplayer names""")
@ConfigInfo(name = "suffix")
public static String suffix = "";
@ConfigInfo(name = "regen-amount", comments = """
Regeneration amount for fakeplayers""")
@ConfigInfo(name = "regen-amount")
public static double regenAmount = 0.0;
@ConfigInfo(name = "open-action-gui", comments = """
Allow opening fakeplayer action gui,
need sneak to open if you enabled inventory open gui""")
@ConfigInfo(name = "open-action-gui")
public static boolean canOpenActionGui = false;
@ConfigInfo(name = "use-action", comments = """
Allow fakeplayers to use actions""")
@ConfigInfo(name = "use-action")
public static boolean canUseAction = true;
@ConfigInfo(name = "modify-config", comments = """
Allow modifying fakeplayer config""")
@ConfigInfo(name = "modify-config")
public static boolean canModifyConfig = false;
@ConfigInfo(name = "manual-save-and-load", comments = """
Allow manual save and load of fakeplayers""")
@ConfigInfo(name = "manual-save-and-load")
public static boolean canManualSaveAndLoad = false;
@ConfigInfo(name = "cache-skin", comments = """
Use skin cache for fakeplayers""")
@ConfigInfo(name = "cache-skin")
public static boolean useSkinCache = false;
@ConfigInfo(name = "always-send-data", comments = """
Always send data for fakeplayers""")
@ConfigInfo(name = "always-send-data")
public static boolean canSendDataAlways = true;
@ConfigInfo(name = "skip-sleep-check", comments = """
Skip sleep check for fakeplayers""")
@ConfigInfo(name = "skip-sleep-check")
public static boolean canSkipSleep = false;
@ConfigInfo(name = "spawn-phantom", comments = """
Allow phantoms to spawn for fakeplayers""")
@ConfigInfo(name = "spawn-phantom")
public static boolean canSpawnPhantom = false;
@ConfigInfo(name = "simulation-distance", comments = """
Simulation distance for fakeplayers (-1 for default)""")
@ConfigInfo(name = "simulation-distance")
public static int simulationDistance = -1;
@ConfigInfo(name = "enable-locator-bar", comments = """
Enable locator bar for fakeplayers""")
@ConfigInfo(name = "enable-locator-bar")
public static boolean enableLocatorBar = false;
@DoNotLoad
@@ -9,18 +9,12 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "language")
public class LanguageConfig implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "lang", comments = """
Please use the key from https://minecraft.wiki/w/Language
Sample of format: en_us zh_cn zh_hk zh_tw
ATTENTION: If you want to edit language for carpet system,
please edit it in carpet config file.""")
@ConfigInfo(name = "lang")
public static String lang = "en_us";
@ConfigInfo(name = "full_blocking_load", comments = """
Whether to allow blocking server loading when loading localized language.
If you want only use your localized language to shown in your terminal,
you need to enable it.
WARNING: This may slow down the startup speed!""")
@ConfigInfo(name = "full_blocking_load")
public static boolean full_blocking_load = false;
@ConfigInfo(name = "allow_auto_reset_comments")
public static boolean allowAutoResetComments = true;
}
@@ -22,8 +22,6 @@ public class OldFeatureConfig implements IConfigModule {
@ConfigInfo(name = "old_raid_behavior")
public static boolean oldRaidBehavior = false;
@ConfigInfo(name = "villager-void-trade", comments =
"""
Allow villager void trade.""")
@ConfigInfo(name = "villager-void-trade")
public static boolean villagerVoidTrade = false;
}
@@ -7,8 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@ConfigInfo(name = "shears_rotate", comments =
"""
Allows you to use the Shears to right-click to rotate the block.""")
@ConfigInfo(name = "shears_rotate")
public static boolean shears = false;
}
@@ -18,13 +18,11 @@ public class ReplayAPIConfig implements IConfigModule {
public static boolean enableCache = true;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-time", comments = """
Time to cache photographer profile(in seconds)""")
@ConfigInfo(name = "cache-photographer-time")
public static int cachePhotographerTime = 3600;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-size", comments = """
Maximum size of cache photographer profile""")
@ConfigInfo(name = "cache-photographer-size")
public static int cachePhotographerSize = 100;
@Override
@@ -8,12 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "alternative_block_placement", directory = {"protocol"})
public class AlternativeBlockPlacementProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Specify the precise placement protocol type
NONE Disable precise placement protocol
CARPET Precise placement protocol version 2
CARPET_FIX Enhanced precise placement protocol version 2 (requires MasaGadget installed on client)
LITEMATICA Precise placement protocol version 3""")
@ConfigInfo(name = "enabled")
public static EnumAlternativePlaceType alternativeBlockPlacement = EnumAlternativePlaceType.NONE;
public static boolean needIgnoreDistance() {
@@ -7,10 +7,8 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "appleskin", directory = {"protocol"})
public class AppleSkinProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable AppleSkin protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "sync-tick-interval", comments = """
Set AppleSkin Synchronization Frequency (Unit: Game Ticks)""")
@ConfigInfo(name = "sync-tick-interval")
public static int syncTickInterval = 20;
}
@@ -7,7 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "bbor", directory = {"protocol"})
public class BBORProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable BBOR protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -7,7 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "jade", directory = {"protocol"})
public class JadeProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Jade protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -1,12 +1,10 @@
package fun.bm.lophine.config.modules.function.protocol;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.carpet.CarpetCompatSync;
import fun.bm.lophine.enums.PcaPlayerEntityType;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.protocol.PcaSyncProtocol;
@@ -17,19 +15,10 @@ import java.util.Set;
public class PcaSyncProtocolConfig implements IConfigModule {
private static boolean lastEnabled = false;
@TransformedConfig(name = "pca-sync-protocol", directory = {"protocol"})
@ConfigInfo(name = "enabled", comments = """
Enable PCA sync protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@TransformedConfig(name = "pca-sync-player-entity", directory = {"protocol"})
@ConfigInfo(name = "sync-player-entity", comments = """
Controls which player entities can be watched through the PCA sync protocol.
NOBODY: never sync player entities
BOT: only sync Lophine fake players
OPS: sync fake players and allow operators to sync real players
OPS_AND_SELF: sync fake players, operators, and a player's own entity
EVERYONE: allow all player entities""")
@ConfigInfo(name = "sync-player-entity")
public static PcaPlayerEntityType syncPlayerEntity = PcaPlayerEntityType.OPS;
@Override
@@ -38,6 +27,5 @@ public class PcaSyncProtocolConfig implements IConfigModule {
PcaSyncProtocol.onConfigModify(enabled);
lastEnabled = enabled;
}
CarpetCompatSync.apply();
}
}
@@ -7,7 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "rei", directory = {"protocol"})
public class REIServerProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Roughly Enough Items protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -39,6 +39,6 @@ public class ServuxProtocolConfig implements IConfigModule {
public static int litematicsMaxNbtSize = 2097152;
@CommandSuggestions(suggest = {"-1", "1200"})
@ConfigInfo(name = "litematics-print-max-delay-ticks", directory = {"litematics"}, comments = "The max delay ticks for printing litematics, -1 to disable")
@ConfigInfo(name = "litematics-print-max-delay-ticks", directory = {"litematics"})
public static int maxDelay = 1200;
}
@@ -12,14 +12,11 @@ import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "syncmatica", directory = {"protocol"})
public class SyncmaticaProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Syncmatica protocol support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "useQuota", comments = """
Is there a limit on the size of projection files?""")
@ConfigInfo(name = "useQuota")
public static boolean useQuota = false;
@ConfigInfo(name = "quota-Limit", comments = """
Maximum Projection File Size (in bytes)""")
@ConfigInfo(name = "quota-Limit")
public static int quotaLimit = 40000000;
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
@@ -9,8 +9,7 @@ import java.util.Random;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "xaero-map", directory = {"protocol"})
public class XaeroMapProtocolConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Enable Xaero World Map Protocol Support""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "xaeroMapServerID")
public static int xaeroMapServerID = new Random().nextInt();
@@ -7,11 +7,9 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "disable-check")
public class DisableCheckConfig implements IConfigModule {
@ConfigInfo(name = "disable-op-move-check", comments = """
Disable the check for the operator's move check""")
@ConfigInfo(name = "disable-op-move-check")
public static boolean disableOpMoveCheck = false;
@ConfigInfo(name = "disable-op-fly-check", comments = """
Disable the check for the operator's fly check""")
@ConfigInfo(name = "disable-op-fly-check")
public static boolean disableOpFlyCheck = false;
}
@@ -7,10 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "item-entity")
public class ItemEntityConfig implements IConfigModule {
@ConfigInfo(name = "follow-tick-sequence-merge", comments = """
Due to Paper's modification of the merge radius,
when the merge radius is large and stacks containing many items get stuck in an unexpected position,
individual items may never reach their destination.
This configuration option is added to fix this behavior.""")
@ConfigInfo(name = "follow-tick-sequence-merge")
public static boolean followTickSequenceMerge = false;
}
@@ -7,8 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.REMOVED, name = "removed_config")
public class RemovedConfig implements IConfigModule {
@ConfigInfo(name = "removed", comments =
"""
RemovedConfig redirect to here, no any function.""")
@ConfigInfo(name = "removed")
public static boolean enabled = true;
}
@@ -109,6 +109,11 @@ public class ServerI18nUtil {
}
Language.inject(createLangInstance());
logger.info("Successfully loaded language: {}", lang);
if (LanguageConfig.allowAutoResetComments) {
logger.info("Start trying to load localized comments.");
ConfigManager.reloadComments();
logger.info("Loaded all comments.");
}
} catch (Exception e) {
if (e instanceof MalformedJsonException malformedJson) {
malformedJson.clean();
@@ -297,6 +302,12 @@ public class ServerI18nUtil {
}
}
public static String getLocalizedComment(String key) {
String current = Language.getInstance().getOrDefault(key, "");
if (!current.isBlank()) return current;
return Language.DEFAULT_INSTANCE.getOrDefault(key, "");
}
private static class UnsupportedLanguageException extends Exception {
}
@@ -13,7 +13,7 @@ import java.util.List;
public class BarSubcommand extends LiteralNode {
public BarSubcommand(EnumBarType barType) {
super(barType.getCommandName());
super(barType.getName());
children(
new ToggleCommand(barType),
new ConfigEditCommand(barType)
@@ -152,4 +152,13 @@ public class ConfigManager {
toReload.forEach(ConfigsInstance::saveConfigs);
needTransformedConfigs.clear(); // free space when all done
}
public static void reloadComments() {
CompletableFuture<?>[] futures = configfiles.values().stream()
.map(config -> CompletableFuture.runAsync(() -> {
config.reload(false, false);
}))
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
}
}
@@ -3,6 +3,7 @@ package me.earthme.luminol.config;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.utils.ServerI18nUtil;
import io.papermc.paper.threadedregions.RegionizedServer;
import me.earthme.luminol.api.config.ConfigDataPair;
import me.earthme.luminol.api.config.LuminolConfigsInstance;
@@ -150,6 +151,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
// if the config load with exceptions but allowed, remove exceptions from the map
allInstanced.replaceAll((_, _) -> null);
setupLatch();
saveConfigs();
}
/**
@@ -256,28 +258,12 @@ public class ConfigsInstance implements LuminolConfigsInstance {
}
}
loadCategoryComments(); // load base key comment
allInstanced.putAll(stagedMap);
}
/**
* Load config category comments
*/
private void loadCategoryComments() {
for (EnumConfigCategory category : EnumConfigCategory.values()) {
String key = category.getBaseKeyName();
if (key == null) continue;
String comment = category.getKeyComment();
if (comment == null) continue;
if (!completeConfigPath(key).isEmpty()) {
String comment0 = configFileInstance.getComment(key);
if (comment0 == null) {
configFileInstance.setComment(key, comment);
}
}
}
}
/**
* Instantiate all configuration modules
@@ -303,7 +289,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
// Build configuration path and handle class comments
final List<String> category = buildConfigCategoryPath(configClassInfo);
final String fullConfigBasePath = String.join(".", category);
handleClassLevelComments(configClassInfo, fullConfigBasePath);
handleClassLevelComments(fullConfigBasePath, keepComments);
// Process each field in the module
Field[] fields = singleConfigModule.getClass().getDeclaredFields();
@@ -340,12 +326,18 @@ public class ConfigsInstance implements LuminolConfigsInstance {
/**
* Handle class-level comments for configuration
*/
private void handleClassLevelComments(ConfigClassInfo configClassInfo, String fullConfigBasePath) {
final String comment = configFileInstance.getComment(fullConfigBasePath);
if (comment == null || comment.isBlank()) {
String comments0 = configClassInfo.comments();
if (!comments0.isBlank()) {
configFileInstance.setComment(fullConfigBasePath, comments0);
private void handleClassLevelComments(String fullConfigBasePath, boolean keepComments) {
final String existingComment = configFileInstance.getComment(fullConfigBasePath);
final String localizedComment = ServerI18nUtil.getLocalizedComment(name + "." + fullConfigBasePath + ".comment");
if (!keepComments) {
// Force reset to localized default
if (!localizedComment.isBlank()) {
configFileInstance.setComment(fullConfigBasePath, localizedComment);
}
} else if (existingComment == null || existingComment.isBlank()) {
// Only fill in when blank
if (!localizedComment.isBlank()) {
configFileInstance.setComment(fullConfigBasePath, localizedComment);
}
}
}
@@ -405,7 +397,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
private void handleMissingOrRemovedConfig(Field field, String fullConfigKeyName,
ConfigInfo configInfo, boolean removed) throws IllegalAccessException {
// Process transformed configurations
processTransformedConfigs(field, fullConfigKeyName, configInfo, removed);
processTransformedConfigs(field, fullConfigKeyName, removed);
// Handle removed configurations
if (removed) {
@@ -440,7 +432,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
}
// Add default value with comments
final String comments = configInfo.comments();
final String comments = ServerI18nUtil.getLocalizedComment(name + "." + fullConfigKeyName + ".comment");
if (!comments.isBlank()) {
configFileInstance.setComment(fullConfigKeyName, comments);
}
@@ -451,8 +443,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
/**
* Process transformed configurations
*/
private void processTransformedConfigs(Field field, String fullConfigKeyName,
ConfigInfo configInfo, boolean removed) {
private void processTransformedConfigs(Field field, String fullConfigKeyName, boolean removed) {
for (TransformedConfig transformedConfig : field.getAnnotationsByType(TransformedConfig.class)) {
final String oldConfigKeyName = String.join(".", transformedConfig.directory()) + "." + transformedConfig.name();
@@ -485,7 +476,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
removeConfig(oldConfigKeyName, transformedConfig.directory());
}
final String comments = configInfo.comments();
final String comments = ServerI18nUtil.getLocalizedComment(name + "." + fullConfigKeyName + ".comment");
if (!comments.isBlank()) {
configFileInstance.setComment(fullConfigKeyName, comments);
}
@@ -526,7 +517,7 @@ public class ConfigsInstance implements LuminolConfigsInstance {
// Handle comments
if (!keepComments) {
final String comments = configInfo.comments();
final String comments = ServerI18nUtil.getLocalizedComment(name + "." + fullConfigKeyName + ".comment");
configFileInstance.setComment(fullConfigKeyName, comments);
}
@@ -12,6 +12,4 @@ public @interface ConfigClassInfo {
String name();
String[] directory() default {};
String comments() default "";
}
@@ -9,7 +9,5 @@ public @interface ConfigInfo {
String[] directory() default {};
String comments() default "";
boolean allowAutoReset() default true;
}
@@ -11,16 +11,9 @@ public class CommandConfig implements IConfigModule {
@ConfigInfo(name = "enable_data_command")
@HotReloadUnsupported
public static boolean data = false;
@ConfigInfo(name = "enable_command_block", comments = """
Force to enable command blocks.
ATTENTION: WOULD CAUSE SERVER CRASHING AS SOME THREADING ISSUE!!!
DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING!!!
""")
@ConfigInfo(name = "enable_command_block")
public static boolean commandBlock = false;
@ConfigInfo(name = "enable_waypoints_and_waypoint_command", comments = """
Enable waypoint and waypoint command.
WARN: Still under testing
""")
@ConfigInfo(name = "enable_waypoints_and_waypoint_command")
@HotReloadUnsupported
public static boolean waypointsAndWaypointCommand = false;
}
@@ -7,11 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "disable_async_catchers")
public class DisableAsyncCatcherConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Disable async catcher to prevent some crashes caused by some plugins which supports folia but has issuable logics.
ATTENTION: Would cause region deadlock when getChunkAt was incorrectly called!
See: https://github.com/PaperMC/Folia/issues/280 which is resolved in folia(https://github.com/PaperMC/Folia/commit/2e7bc0721af95196c85500c7bb136aeea0bc12ce)
DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING!!!
""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -7,9 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "disable_entity_exception_catchers")
public class DisableEntityCatchConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
If this config enabled, the server will crash directly when entity ticking has some errors instead of removing the entity to keep server running.
It could prevent entity disappearing but may cause more server crashes.
DO NOT ENABLE UNLESS YOU KNOW WHAT YOU ARE DOING!!!""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -10,13 +10,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "collision_behavior")
public class CollisionBehaviorConfig implements IConfigModule {
@CommandSuggestions(suggest = {"VANILLA", "BLOCK_SHAPE_VANILLA", "PAPER"})
@ConfigInfo(name = "mode", comments =
"""
Decides which collision logics will be used(Moonrise and Paper modified this for optimization but would also break some vanilla behaviours at the same time).
Would be useful for fixing improper behaviours of some huge redstone machines
Available Value:
VANILLA
BLOCK_SHAPE_VANILLA
PAPER""")
@ConfigInfo(name = "mode")
public static EnumCollisionBehaviorMode behaviorMode = EnumCollisionBehaviorMode.BLOCK_SHAPE_VANILLA;
}
@@ -7,13 +7,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "fix_high_velocity_issue")
public class FoliaEntityMovingFixConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments =
"""
A simple fix of an issue on folia\s
(Sometimes the entity would\s
have a large moment that cross the\s
different tick regions, and it would\s
make the server crashed) but sometimes it might doesn't work""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "warn_on_detected")
@@ -5,14 +5,14 @@ import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "force_cleanup_drop_non_owned_entity_memory_module", comments = "This config is a temporary fix for those incorrect owned data in the memory of each mob, for more you can see https://github.com/PaperMC/Folia/issues/203")
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "force_cleanup_drop_non_owned_entity_memory_module")
public class ForceCleanupEntityBrainMemoryConfig implements IConfigModule {
@ConfigInfo(name = "enabled_for_entity", comments = "When enabled, the entity's brain will clean the memory which is typed of entity and not belong to current tickregion")
@ConfigInfo(name = "enabled_for_entity")
public static boolean enabledForEntity = false;
@ConfigInfo(name = "enabled_for_block_pos", comments = "When enabled, the entity's brain will clean the memory which is typed of block_pos and not belong to current tickregion")
@ConfigInfo(name = "enabled_for_block_pos")
public static boolean enabledForBlockPos = false;
@ConfigInfo(name = "enabled_for_position_tracker", comments = "When enabled, the entity's brain will clean the memory which is typed of position_tracker and not belong to current tickregion")
@ConfigInfo(name = "enabled_for_position_tracker")
public static boolean enabledForPositionTracker = false;
}
@@ -7,8 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "item_multitask")
public class ItemMultitaskConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Prevent the server from interrupting the state of items
during block interactions or hotbar slot changes.""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
}
@@ -6,9 +6,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "long_command_support")
public class LongCommandSupportConfig {
@ConfigInfo(name = "enabled", comments = """
Some long commands can be run through the dialog command,
but paper has prohibited it.
Enable this to fix this problem.""")
@ConfigInfo(name = "enabled")
public static boolean enabled = true;
}
@@ -7,9 +7,6 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(name = "poi_range_fixes", category = EnumConfigCategory.FIXES)
public class POIRangeFixes implements IConfigModule {
@ConfigInfo(name = "do_not_compete_poi_if_unloaded", comments = """
Do not compete POI if it's unloaded
Related with https://github.com/PaperMC/Folia/issues/292
""")
@ConfigInfo(name = "do_not_compete_poi_if_unloaded")
public static boolean doNotCompetePOIIfUnloaded = false;
}
@@ -7,8 +7,8 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "pathfinding_fixes")
public class PathfindingFixesConfig implements IConfigModule {
@ConfigInfo(name = "break_down_pathfinding_when_out_of_region", comments = "Recompute path or stop pathfinding when it's touching the blocks out of current tick region")
@ConfigInfo(name = "break_down_pathfinding_when_out_of_region")
public static boolean breakDownPathfindingWhenOutOfRegion = false;
@ConfigInfo(name = "do_not_pathfind_to_not_owned_targets", comments = "Skip pathfinding target when it's out of current tick region")
@ConfigInfo(name = "do_not_pathfind_to_not_owned_targets")
public static boolean doNotPathfindToNotOwnedTargets = false;
}
@@ -7,10 +7,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "prevent_incorrect_teleport_async_calls_during_move_event")
public class PreventIncorrectTeleportAsyncConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
When enabled, the server would reject some incorrect teleportAsync calls during move events.
And this will reduce the crashes which caused by plugins(Residence etc.)
But you should notice that it might break the compatibility with some plugins.""")
@ConfigInfo(name = "enabled")
public static boolean enabled = false;
@ConfigInfo(name = "throw_when_caught")

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