diff --git a/.github/workflows/build_1.21.4.yml b/.github/workflows/build_1.21.4.yml
index 52f0862..4b1b6eb 100644
--- a/.github/workflows/build_1.21.4.yml
+++ b/.github/workflows/build_1.21.4.yml
@@ -27,7 +27,7 @@ jobs:
- name: Configure Git User Details
run: git config --global user.email "ci@luminolmc.com" && git config --global user.name "LuminolMC CI"
- name: Apply Patches
- run: ./gradlew applyPatches
+ run: ./gradlew applyAllPatches
- name: CreateJar
run: ./gradlew createMojmapPaperclipJar
- name: Publish to repo
diff --git a/.gitignore b/.gitignore
index ab0cb4c..b0b71e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,59 +1,16 @@
-# JVM crash related
-core.*
-hs_err_pid*
+# Ignore Gradle project-specific cache directory
+.gradle
+
+# Ignore Gradle build output directory
+build
+
+/run
+
+/folia-server/build.gradle.kts
+/folia-server/src/minecraft
+/paper-server
+/folia-api/build.gradle.kts
+/paper-api
+/paper-api-generator
-# Intellij
.idea/
-*.iml
-*.ipr
-*.iws
-out/
-
-# Eclipse
-.classpath
-.project
-.settings/
-
-# netbeans
-nbproject/
-nbactions.xml
-
-# Gradle
-!gradle-wrapper.jar
-.gradle/
-build/
-*/build/
-
-# we use maven!
-build.xml
-
-# Maven
-log/
-target/
-dependency-reduced-pom.xml
-
-# various other potential build files
-bin/
-dist/
-manifest.mf
-
-# Mac
-.DS_Store/
-.DS_Store
-
-# vim
-.*.sw[a-p]
-
-# Linux temp files
-*~
-
-# other stuff
-run/
-
-# Luminol
-build-data/
-Luminol-API
-Luminol-Server
-paper-api-generator
-*.jar
-/patches2/todo/
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 980f302..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2024 LuminolMC
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
deleted file mode 100644
index d55f5d7..0000000
--- a/README.md
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-# Luminol
-
Luminol is a Folia fork with many useful optimizations, configurable vanilla features, and more API supports, and it was designed for survival and anarchy servers
-
-[](LICENSE)
-[](https://github.com/LuminolMC/Luminol/issues)
-
-
-
-
-**English** | [中文](./README.md)
-
-## Features
-- Configurable vanilla features
-- Tpsbar support
-- Linear region file format(from kaiiju)
-- Useful optimizations to improve the performance of single threaded region
-- More API support for plugin development (W.I.P)
-
-## Download
-Any versions are available in the [release](https://github.com/LuminolMC/Luminol/releases), also you can build it by yourself through [the following steps](./README_EN.md#build).
-
-## Build
-To build a paperclip jar, you need to run the following command. You can find the jar in build/libs(Note: JDK21 is needed)
-
- ```shell
- ./gradlew applyPatches && ./gradlew createMojmapPaperclipJar
-```
-
-## Using API
-For gradle:
-
-```kotlin
-repositories {
- maven {
- url = "https://maven.moliatopia.icu/repository/maven-snapshots/"
- }
-}
-
-dependencies {
- compileOnly("me.earthme.luminol:luminol-api:1.21.3-R0.1-20241201.004037-1")
-}
- ```
-
-For maven
-
-```xml
-
-
- moliatopia
- https://maven.moliatopia.icu/repository/maven-snapshots/
-
-
-
-
-
- me.earthme.luminol
- luminol-api
- 1.21.3-R0.1-20241201.004037-1
-
-
-```
-
-## Contact
-> If you are interested in this project or have any issue, feel free to ask us.
-
-**QQ Group: [368632360](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=MfosKhcDd8Fdxn1MREuZ8Krbf9T6jiBC&authKey=3cm6qdHohON3gHnuD63FK4k07fIbrWnY4hdyq8OmELsfjMVP1kbFTJY9mRyM2Rkj&noverify=0&group_code=368632360)** | QQ Channel: [Click To Join](https://pd.qq.com/s/eq9krf9j) | Telegram: [Click To Join](https://t.me/LuminolMC) | Discord: [Click To Join](https://discord.gg/Qd7m3V6eDx)
-
-## About Issue
-When you meet any problems, just ask us, we will do our best to solve it, but remember to state your problem clear and provide enough logs etc.
-
-## Pull Requests
-See [Contributing](./docs/CONTRIBUTING_EN.md)
-
-## BStats
-
-
-## Please ⭐star us!
-
-
-
-
-
-
-
diff --git a/build.gradle.kts b/build.gradle.kts
index 2c16572..10b9a40 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,113 +1,97 @@
-plugins {
- java
- `maven-publish`
- id("io.papermc.paperweight.patcher") version "1.7.7"
-}
-
-val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
-
-repositories {
- mavenCentral()
- maven(paperMavenPublicUrl) {
- content { onlyForConfigurations(configurations.paperclip.name) }
- }
-}
-
-dependencies {
- remapper("net.fabricmc:tiny-remapper:0.10.3:fat")
- decompiler("org.vineflower:vineflower:1.10.1")
- paperclip("io.papermc:paperclip:3.0.3")
-}
-
-subprojects {
- apply(plugin = "java")
- apply(plugin = "maven-publish")
-
- java {
- toolchain {
- languageVersion.set(JavaLanguageVersion.of(21))
- }
- }
-
- tasks.withType {
- options.encoding = Charsets.UTF_8.name()
- options.release.set(21)
- }
-
- tasks.withType {
- options.encoding = Charsets.UTF_8.name()
- }
-
- tasks.withType {
- filteringCharset = Charsets.UTF_8.name()
- }
-
- repositories {
- mavenCentral()
- maven(paperMavenPublicUrl)
- }
-}
-
-paperweight {
- serverProject.set(project(":luminol-server"))
-
- remapRepo.set(paperMavenPublicUrl)
- decompileRepo.set(paperMavenPublicUrl)
-
- useStandardUpstream("folia") {
- url.set(github("PaperMC", "Folia"))
- ref.set(providers.gradleProperty("foliaCommit"))
-
- withStandardPatcher {
- apiSourceDirPath.set("Folia-API")
- serverSourceDirPath.set("Folia-Server")
-
-
- apiPatchDir.set(layout.projectDirectory.dir("patches/api"))
- apiOutputDir.set(layout.projectDirectory.dir("Luminol-API"))
-
- serverPatchDir.set(layout.projectDirectory.dir("patches/server"))
- serverOutputDir.set(layout.projectDirectory.dir("Luminol-Server"))
- }
-
- patchTasks.register("generatedApi") {
- isBareDirectory = true
- upstreamDirPath = "paper-api-generator/generated"
- patchDir = layout.projectDirectory.dir("patches/generatedApi")
- outputDir = layout.projectDirectory.dir("paper-api-generator/generated")
- }
- }
-}
-
-tasks.generateDevelopmentBundle {
- apiCoordinates.set("me.earthme.luminol:luminol-api")
- libraryRepositories.addAll(
- "https://repo.maven.apache.org/maven2/",
- "https://maven.pkg.github.com/LuminolMC/Luminol",
- paperMavenPublicUrl,
- )
-}
-
-allprojects {
- publishing {
- repositories {
- maven {
- name = "moliaMavenRepo"
- url = uri("https://maven.moliatopia.icu/repository/maven-snapshots/")
-
- credentials.username = System.getenv("MAVEN_REPO_USER")
- credentials.password = System.getenv("MAVEN_REPO_PASSWORD")
- }
- }
- }
-}
-
-publishing {
- if (project.hasProperty("publishDevBundle")) {
- publications.create("devBundle") {
- artifact(tasks.generateDevelopmentBundle) {
- artifactId = "dev-bundle"
- }
- }
- }
-}
+import org.gradle.api.tasks.testing.logging.TestExceptionFormat
+import org.gradle.api.tasks.testing.logging.TestLogEvent
+
+plugins {
+ java // TODO java launcher tasks
+ id("io.papermc.paperweight.patcher") version "2.0.0-beta.13"
+}
+
+paperweight {
+ upstreams.register("folia") {
+ repo = github("PaperMC", "Folia")
+ ref = providers.gradleProperty("foliaRef")
+
+ patchFile {
+ path = "folia-server/build.gradle.kts"
+ outputFile = file("luminol-server/build.gradle.kts")
+ patchFile = file("luminol-server/build.gradle.kts.patch")
+ }
+ patchFile {
+ path = "folia-api/build.gradle.kts"
+ outputFile = file("luminol-api/build.gradle.kts")
+ patchFile = file("luminol-api/build.gradle.kts.patch")
+ }
+ patchRepo("paperApi") {
+ upstreamPath = "paper-api"
+ patchesDir = file("luminol-api/paper-patches")
+ outputDir = file("paper-api")
+ }
+ patchRepo("paperApiGenerator") {
+ upstreamPath = "paper-api-generator"
+ patchesDir = file("luminol-api-generator/paper-patches")
+ outputDir = file("paper-api-generator")
+ }
+ patchDir("foliaApi") {
+ upstreamPath = "folia-api"
+ excludes = listOf("build.gradle.kts", "build.gradle.kts.patch", "paper-patches")
+ patchesDir = file("luminol-api/folia-patches")
+ outputDir = file("folia-api")
+ }
+ }
+}
+
+val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
+
+subprojects {
+ apply(plugin = "java-library")
+ apply(plugin = "maven-publish")
+
+ extensions.configure {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(21)
+ }
+ }
+
+ repositories {
+ mavenCentral()
+ maven(paperMavenPublicUrl)
+ }
+
+ dependencies {
+ "testRuntimeOnly"("org.junit.platform:junit-platform-launcher")
+ }
+
+ tasks.withType().configureEach {
+ isPreserveFileTimestamps = false
+ isReproducibleFileOrder = true
+ }
+ tasks.withType {
+ options.encoding = Charsets.UTF_8.name()
+ options.release = 21
+ options.isFork = true
+ }
+ tasks.withType {
+ options.encoding = Charsets.UTF_8.name()
+ }
+ tasks.withType {
+ filteringCharset = Charsets.UTF_8.name()
+ }
+ tasks.withType {
+ testLogging {
+ showStackTraces = true
+ exceptionFormat = TestExceptionFormat.FULL
+ events(TestLogEvent.STANDARD_OUT)
+ }
+ }
+
+ extensions.configure {
+ repositories {
+ /*
+ maven("https://repo.papermc.io/repository/maven-snapshots/") {
+ name = "paperSnapshots"
+ credentials(PasswordCredentials::class)
+ }
+ */
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
index a9a973c..2de9082 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,13 +1,10 @@
group = me.earthme.luminol
-version = 1.21.4-R0.1-SNAPSHOT
+version=1.21.4-R0.1-SNAPSHOT
+mcVersion=1.21.4
-foliaCommit = 8af1aef1f14630ede6575a72632e7f943d8fb903
+foliaRef=7dbde1de0027da125f6d97cb0b235340c9887afb
-org.gradle.caching = true
-org.gradle.parallel = true
-org.gradle.vfs.watch = false
-org.gradle.jvmargs = -Xmx3G
-
-mcVersion = 1.21.4
-GroupMCV = 1.21
-preVersion = false
\ No newline at end of file
+org.gradle.configuration-cache=true
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.vfs.watch=false
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e2847c8..cea7a79 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index f5feea6..f3b75f3 100755
--- a/gradlew
+++ b/gradlew
@@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
-' "$PWD" ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
diff --git a/patches/api/0001-Rebrand-to-Luminol.patch b/luminol-api/paper-patches/features/0001-Rebrand-to-Luminol.patch
similarity index 88%
rename from patches/api/0001-Rebrand-to-Luminol.patch
rename to luminol-api/paper-patches/features/0001-Rebrand-to-Luminol.patch
index 4c43eef..488ab37 100644
--- a/patches/api/0001-Rebrand-to-Luminol.patch
+++ b/luminol-api/paper-patches/features/0001-Rebrand-to-Luminol.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
-Date: Tue, 21 May 2024 21:31:53 +0800
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:18:38 +0800
Subject: [PATCH] Rebrand to Luminol
diff --git a/patches/api/0003-KioCG-Chunk-API.patch b/luminol-api/paper-patches/features/0002-KioCG-Chunk-API.patch
similarity index 69%
rename from patches/api/0003-KioCG-Chunk-API.patch
rename to luminol-api/paper-patches/features/0002-KioCG-Chunk-API.patch
index fd11354..4b06fbd 100644
--- a/patches/api/0003-KioCG-Chunk-API.patch
+++ b/luminol-api/paper-patches/features/0002-KioCG-Chunk-API.patch
@@ -1,14 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Fri, 25 Oct 2024 00:07:15 +0800
+Date: Sun, 12 Jan 2025 11:45:16 +0800
Subject: [PATCH] KioCG Chunk API
diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java
-index bc8b5bc17706250b8535b1b309134843d2ce2bb1..1cfe84ad1094e3c4fab96487f328be53e035a64c 100644
+index d434277342b2db19f98e032d3a316b27d728b840..e188353ad193f6203533790ae52fafc0554df63f 100644
--- a/src/main/java/org/bukkit/Chunk.java
+++ b/src/main/java/org/bukkit/Chunk.java
-@@ -389,4 +389,6 @@ public interface Chunk extends PersistentDataHolder {
+@@ -388,4 +388,6 @@ public interface Chunk extends PersistentDataHolder {
*/
UNLOADED;
}
@@ -16,10 +16,10 @@ index bc8b5bc17706250b8535b1b309134843d2ce2bb1..1cfe84ad1094e3c4fab96487f328be53
+ long getChunkHotAvg(); // KioCG
}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 95f0b3186e313c7fbd5c8531d52b82a69e525f94..ce98b3de2fe935de4c280f7af9940499d6f09926 100644
+index 7d21ee64c9b9c14412a1eddb63fae812a91e7d9c..83e8a442a909ca2595d2eb0946c804e0814bc9a8 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
-@@ -3911,4 +3911,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+@@ -3892,4 +3892,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/
void sendEntityEffect(org.bukkit.@NotNull EntityEffect effect, @NotNull Entity target);
// Paper end - entity effect API
diff --git a/patches/api/0006-Disable-timings-warn-msg-and-commands.patch b/luminol-api/paper-patches/features/0003-Disable-timings-warn-msg-and-commands.patch
similarity index 95%
rename from patches/api/0006-Disable-timings-warn-msg-and-commands.patch
rename to luminol-api/paper-patches/features/0003-Disable-timings-warn-msg-and-commands.patch
index 090c1fa..cee04fa 100644
--- a/patches/api/0006-Disable-timings-warn-msg-and-commands.patch
+++ b/luminol-api/paper-patches/features/0003-Disable-timings-warn-msg-and-commands.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 30 Nov 2024 12:34:50 +0800
+Date: Sun, 12 Jan 2025 12:22:53 +0800
Subject: [PATCH] Disable timings warn msg and commands
@@ -31,7 +31,7 @@ index 5df19bd701c67506689fc7f49d91f99ebfbc83f0..baf0cbd2f995ebe2e4382244eff6e15e
public void setFallbackCommands() {
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index 9611e8e254b4fa9579dc9ffd5198182c43819c56..170fefdc50605c0c4d742a606c18d871966e6e72 100644
+index 468f5646da7bc413a6e91e82379e6554cc8b459d..ab36e3aaff57e2f27b5aed06b4bdfe277f86a35e 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
@@ -966,7 +966,7 @@ public final class SimplePluginManager implements PluginManager {
diff --git a/luminol-server/build.gradle.kts b/luminol-server/build.gradle.kts
index 5a20196..55ab129 100644
--- a/luminol-server/build.gradle.kts
+++ b/luminol-server/build.gradle.kts
@@ -165,6 +165,13 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
dependencies {
implementation(project(":luminol-api")) // Luminol
+ implementation("com.electronwill.night-config:toml:3.6.6") // Luminol - Night config
+ // Abomination start
+ implementation("com.github.luben:zstd-jni:1.5.4-1")
+ implementation("org.lz4:lz4-java:1.8.0")
+ implementation("net.openhft:zero-allocation-hashing:0.16")
+ // Abomination end
+ implementation("io.github.classgraph:classgraph:4.8.158") // Kaiiju - Entity throttling & Removal
implementation("ca.spottedleaf:concurrentutil:0.0.3")
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
diff --git a/luminol-server/minecraft-patches/features/0001-Added-luminol-config-framework.patch b/luminol-server/minecraft-patches/features/0001-Added-luminol-config-framework.patch
new file mode 100644
index 0000000..7cd8660
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0001-Added-luminol-config-framework.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:15:52 +0800
+Subject: [PATCH] Added luminol config framework
+
+
+diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
+index 9aa664537cc37e44db46d5a2a64ae3116938c681..8d6a6534a134e99e5ee2652d7b0c858d538e69bd 100644
+--- a/net/minecraft/server/Main.java
++++ b/net/minecraft/server/Main.java
+@@ -108,6 +108,7 @@ public class Main {
+ JvmProfiler.INSTANCE.start(Environment.SERVER);
+ }
+
++ me.earthme.luminol.config.LuminolConfig.preLoadConfig(); // Luminol - Luminol 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 341e400f789e0eda29827e2c45c483a470d2e982..8f348d140ab98e23ee0debe4bacac51fee49c35e 100644
+--- a/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -212,6 +212,8 @@ 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
+ this.server.spark.enableEarlyIfRequested(); // Paper - spark
+ // Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
+ if (this.convertOldUsers()) {
diff --git a/luminol-server/minecraft-patches/features/0002-Add-config-for-server-mod-name.patch b/luminol-server/minecraft-patches/features/0002-Add-config-for-server-mod-name.patch
new file mode 100644
index 0000000..9a6eb54
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0002-Add-config-for-server-mod-name.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:17:52 +0800
+Subject: [PATCH] Add config for server mod name
+
+
+diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
+index faf72dd6dff74296c73cb058aaabd1f9f475a072..46375fa81b36b89b79c22f0a7ac6d610ab1183d4 100644
+--- a/net/minecraft/server/MinecraftServer.java
++++ b/net/minecraft/server/MinecraftServer.java
+@@ -1967,7 +1967,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
+Date: Sun, 12 Jan 2025 10:23:13 +0800
+Subject: [PATCH] Add config for unsafe teleportation
+
+
+diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java
+index 1fa5e6a12b943e889bde566038a632a6adcf319e..c1f6a3b3a8fa990b8e9b052341ab31bde7c04e7a 100644
+--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
+@@ -65,7 +65,7 @@ public class FallingBlockEntity extends Entity {
+ public float fallDamagePerDistance;
+ @Nullable
+ public CompoundTag blockData;
+- public boolean forceTickAfterTeleportToDuplicate;
++ public boolean forceTickAfterTeleportToDuplicate = me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled; // Luminol - Unsafe teleportation
+ protected static final EntityDataAccessor DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
+ public boolean autoExpire = true; // Paper - Expand FallingBlock API
+
+@@ -401,7 +401,7 @@ public class FallingBlockEntity extends Entity {
+ ResourceKey resourceKey1 = this.level().dimension();
+ boolean flag = (resourceKey1 == Level.END || resourceKey == Level.END) && resourceKey1 != resourceKey;
+ Entity entity = super.teleport(teleportTransition);
+- this.forceTickAfterTeleportToDuplicate = entity != null && flag && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper
++ this.forceTickAfterTeleportToDuplicate = entity != null && flag && (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation || me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled); // Paper // Luminol - Unsafe teleportation
+ return entity;
+ }
+ }
+diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java
+index 177735cf744e564081e4c140a0f8210c3a07e037..7274f2d7df9228f34305a21abde6d114a495c1cb 100644
+--- a/net/minecraft/world/level/block/EndPortalBlock.java
++++ b/net/minecraft/world/level/block/EndPortalBlock.java
+@@ -67,6 +67,11 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
+ if (level.paperConfig().misc.disableEndCredits) {serverPlayer.seenCredits = true; return;} // Paper - Option to disable end credits
+ serverPlayer.showEndCredits();
+ } else {
++ // Luminol start - unsafe teleportation
++ if (me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled && !(entity instanceof net.minecraft.world.entity.player.Player)) {
++ entity.endPortalLogicAsync(pos);
++ }
++ // Luminol end
+ entity.setAsInsidePortal(this, pos);
+ }
+ }
diff --git a/luminol-server/minecraft-patches/features/0004-Add-config-for-vanilla-random.patch b/luminol-server/minecraft-patches/features/0004-Add-config-for-vanilla-random.patch
new file mode 100644
index 0000000..09fdf8c
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0004-Add-config-for-vanilla-random.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:24:50 +0800
+Subject: [PATCH] Add config for vanilla random
+
+
+diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
+index 597520a680bc1a54055b99f93724682a4d940458..4cfc228a60a147409b8afc4cb138ce6437a9b667 100644
+--- a/net/minecraft/world/entity/Entity.java
++++ b/net/minecraft/world/entity/Entity.java
+@@ -255,7 +255,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ public double zOld;
+ public boolean noPhysics;
+ private boolean wasOnFire;
+- public final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
++ public final RandomSource random = me.earthme.luminol.config.modules.fixes.VanillaRandomSourceConfig.useLegacyRandomSourceForPlayers ? RandomSource.create() : SHARED_RANDOM; // Paper - Share random for entities to make them more random // Luminol - Add config for vanilla random SHARED_RANDOM
+ public int tickCount;
+ private int remainingFireTicks = -this.getFireImmuneTicks();
+ public boolean wasTouchingWater;
diff --git a/luminol-server/minecraft-patches/features/0005-Add-a-simple-tpsbar.patch b/luminol-server/minecraft-patches/features/0005-Add-a-simple-tpsbar.patch
new file mode 100644
index 0000000..9903946
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0005-Add-a-simple-tpsbar.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:27:31 +0800
+Subject: [PATCH] Add a simple tpsbar
+
+
+diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
+index 8f348d140ab98e23ee0debe4bacac51fee49c35e..852d598fc11a9640a20b093839707c3a5a96e057 100644
+--- a/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -764,6 +764,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
+
+ @Override
+ public void stopServer() {
++ me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar
+ super.stopServer();
+ //Util.shutdownExecutors(); // Paper - Improved watchdog support; moved into super
+ SkullBlockEntity.clear();
+diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
+index ca3770e9f77e583dfa6cef8ca884eaf6a43f5ffa..465f20e5f24a8b37fb31393bcedd3807896666c7 100644
+--- a/net/minecraft/server/level/ServerPlayer.java
++++ b/net/minecraft/server/level/ServerPlayer.java
+@@ -393,7 +393,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
+ public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
+ public @Nullable String clientBrandName = null; // Paper - Brand support
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
+-
++ public volatile boolean isTpsBarVisible = false; //Luminol - Tps bar
+ // Paper start - rewrite chunk system
+ private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
+ private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
diff --git a/luminol-server/minecraft-patches/features/0006-Add-a-simple-membar.patch b/luminol-server/minecraft-patches/features/0006-Add-a-simple-membar.patch
new file mode 100644
index 0000000..2968045
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0006-Add-a-simple-membar.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:28:03 +0800
+Subject: [PATCH] Add a simple membar
+
+
+diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
+index 852d598fc11a9640a20b093839707c3a5a96e057..cc80198a5d5f4e9188ef35944d077200f03ac43b 100644
+--- a/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -765,6 +765,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
+ @Override
+ public void stopServer() {
+ me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar
++ me.earthme.luminol.functions.GlobalServerMemoryBar.cancelBarUpdateTask(); //Luminol - Memory bar
+ super.stopServer();
+ //Util.shutdownExecutors(); // Paper - Improved watchdog support; moved into super
+ SkullBlockEntity.clear();
+diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
+index 465f20e5f24a8b37fb31393bcedd3807896666c7..b4a4eec6029f1aee5f3b0da6938a9b23db36d5f9 100644
+--- a/net/minecraft/server/level/ServerPlayer.java
++++ b/net/minecraft/server/level/ServerPlayer.java
+@@ -394,6 +394,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
+ public @Nullable String clientBrandName = null; // Paper - Brand support
+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
+ public volatile boolean isTpsBarVisible = false; //Luminol - Tps bar
++ public volatile boolean isMemBarVisible = false; //Luminol - Memory bar
+ // Paper start - rewrite chunk system
+ private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
+ private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
diff --git a/luminol-server/minecraft-patches/features/0007-Add-config-for-username-check.patch b/luminol-server/minecraft-patches/features/0007-Add-config-for-username-check.patch
new file mode 100644
index 0000000..0f9706a
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0007-Add-config-for-username-check.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:29:26 +0800
+Subject: [PATCH] Add config for username check
+
+
+diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+index 159f2f169d26b436a70006f7bc9bdc481315dd32..2b366fea4d8d376b150786fdc00fd5e2413388f6 100644
+--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
++++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+@@ -176,7 +176,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
+ public void handleHello(ServerboundHelloPacket packet) {
+ Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
+ // Paper start - Validate usernames
+- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
++ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled // Luminol - Add config for username check
++ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
+ && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
+ && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
+diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java
+index 6fb3712f33a84a3612752dcfd9e97d67066f610e..26d37cf8fec2e8b0d3c3c1bbe4693d4c6ca4d4f9 100644
+--- a/net/minecraft/server/players/GameProfileCache.java
++++ b/net/minecraft/server/players/GameProfileCache.java
+@@ -77,7 +77,7 @@ public class GameProfileCache {
+ }
+
+ private static Optional lookupGameProfile(GameProfileRepository profileRepo, String name) {
+- if (!StringUtil.isValidPlayerName(name)) {
++ if (!StringUtil.isValidPlayerName(name) && false) { // Luminol - Add config for username check - Directly return, skip unnecessary following logic
+ return createUnknownProfile(name);
+ } else {
+ final AtomicReference atomicReference = new AtomicReference<>();
diff --git a/luminol-server/minecraft-patches/features/0008-Add-config-for-offline-mode-warning.patch b/luminol-server/minecraft-patches/features/0008-Add-config-for-offline-mode-warning.patch
new file mode 100644
index 0000000..43bcc6a
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0008-Add-config-for-offline-mode-warning.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:29:45 +0800
+Subject: [PATCH] Add config for offline mode warning
+
+
+diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
+index cc80198a5d5f4e9188ef35944d077200f03ac43b..82f80e152a8b7426d711df7df6eae9043cf35e69 100644
+--- a/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -285,7 +285,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
+ String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord";
+ String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/";
+ // Paper end - Add Velocity IP Forwarding Support
+- if (!this.usesAuthentication()) {
++ if (!this.usesAuthentication() && me.earthme.luminol.config.modules.misc.OfflineModeWarningConfig.enabled) { //Luminol - Add config for offline mod warning
+ LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
+ LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
+ // Spigot start
diff --git a/luminol-server/minecraft-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch b/luminol-server/minecraft-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch
new file mode 100644
index 0000000..80728e3
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:30:02 +0800
+Subject: [PATCH] Add config for out-of-order chat checks
+
+
+diff --git a/net/minecraft/network/chat/SignedMessageChain.java b/net/minecraft/network/chat/SignedMessageChain.java
+index f6eed34b2fd72ab74cc9dc4b99ca184d512c0a66..73ef2de5efa8fb48975f70998195df76f6161d16 100644
+--- a/net/minecraft/network/chat/SignedMessageChain.java
++++ b/net/minecraft/network/chat/SignedMessageChain.java
+@@ -45,7 +45,7 @@ public class SignedMessageChain {
+ SignedMessageLink signedMessageLink = SignedMessageChain.this.nextLink;
+ if (signedMessageLink == null) {
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
+- } else if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
++ } else if (me.earthme.luminol.config.modules.misc.InorderChatConfig.enabled && body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) { // Luminol - Add config for out-of-order chat checks
+ this.setChainBroken();
+ throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
+ } else {
diff --git a/luminol-server/minecraft-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch b/luminol-server/minecraft-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch
new file mode 100644
index 0000000..11c2b68
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:31:09 +0800
+Subject: [PATCH] Add config to verify signature only in online-mode
+
+
+diff --git a/net/minecraft/world/entity/player/ProfilePublicKey.java b/net/minecraft/world/entity/player/ProfilePublicKey.java
+index 41a9cc693183e96c83837692e93b177a521d6789..f4a2d1a2d467808b9cb75fc32765ddc27be5fdba 100644
+--- a/net/minecraft/world/entity/player/ProfilePublicKey.java
++++ b/net/minecraft/world/entity/player/ProfilePublicKey.java
+@@ -23,7 +23,7 @@ public record ProfilePublicKey(ProfilePublicKey.Data data) {
+ public static final Codec TRUSTED_CODEC = ProfilePublicKey.Data.CODEC.xmap(ProfilePublicKey::new, ProfilePublicKey::data);
+
+ public static ProfilePublicKey createValidated(SignatureValidator signatureValidator, UUID profileId, ProfilePublicKey.Data data) throws ProfilePublicKey.ValidationException {
+- if (!data.validateSignature(signatureValidator, profileId)) {
++ if (!data.validateSignature(signatureValidator, profileId) && (org.bukkit.Bukkit.getServer().getOnlineMode() && me.earthme.luminol.config.modules.misc.PublickeyVerifyConfig.enabled)) { // Luminol - Verify signature only in online-mode
+ throw new ProfilePublicKey.ValidationException(INVALID_SIGNATURE, org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PUBLIC_KEY_SIGNATURE); // Paper - kick event causes
+ } else {
+ return new ProfilePublicKey(data);
+diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
+index 6a7e5a642e2eaf7d5dffadb81738f7385a38c0af..f16500a50904aade3d984b908b11b8edd9c05ba1 100644
+--- a/net/minecraft/world/level/block/TripWireHookBlock.java
++++ b/net/minecraft/world/level/block/TripWireHookBlock.java
+@@ -215,7 +215,7 @@ public class TripWireHookBlock extends Block {
+ BlockState blockState2 = blockStates[i2];
+ if (blockState2 != null) {
+ BlockState blockState3 = level.getBlockState(blockPos1);
+- if (blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) {
++ if (me.earthme.luminol.config.modules.misc.TripwireConfig.enabled || blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) { // Luminol - Add config for tripwire dupe
+ level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3);
+ }
+ }
diff --git a/luminol-server/minecraft-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch b/luminol-server/minecraft-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch
new file mode 100644
index 0000000..8c2168b
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch
@@ -0,0 +1,18 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:35:13 +0800
+Subject: [PATCH] Add config to disable entity tick catchers
+
+
+diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
+index 5ea7fdf1e337da4c207dd6a53ca942480dd31922..926f5c91eb59277704618fe1910f3dbb38cff002 100644
+--- a/net/minecraft/world/level/Level.java
++++ b/net/minecraft/world/level/Level.java
+@@ -1547,6 +1547,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+ try {
+ consumerEntity.accept(entity);
+ } catch (Throwable var6) {
++ if (me.earthme.luminol.config.modules.experiment.DisableEntityCatchConfig.enabled) throw var6; // Luminol
+ // Paper start - Prevent block entity and entity crashes
+ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
+ MinecraftServer.LOGGER.error(msg, var6);
diff --git a/luminol-server/minecraft-patches/features/0012-Add-experiment-config-for-command-block-command-exec.patch b/luminol-server/minecraft-patches/features/0012-Add-experiment-config-for-command-block-command-exec.patch
new file mode 100644
index 0000000..575fe24
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0012-Add-experiment-config-for-command-block-command-exec.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:36:31 +0800
+Subject: [PATCH] Add experiment config for command block command execution
+
+
+diff --git a/net/minecraft/world/level/BaseCommandBlock.java b/net/minecraft/world/level/BaseCommandBlock.java
+index b02b79ccedb8b87bc22270377dfc36e21ebe1724..3786e8288c3a66a5e986ae2a150d03ce2dd5ed16 100644
+--- a/net/minecraft/world/level/BaseCommandBlock.java
++++ b/net/minecraft/world/level/BaseCommandBlock.java
+@@ -114,7 +114,7 @@ public abstract class BaseCommandBlock implements CommandSource {
+ }
+
+ public boolean performCommand(Level level) {
+- if (true) return false; // Folia - region threading
++ if (!me.earthme.luminol.config.modules.experiment.CommandBlockConfig.enabled) return false; // Folia - region threading // Luminol
+ if (level.isClientSide || level.getGameTime() == this.lastExecution) {
+ return false;
+ } else if ("Searge".equalsIgnoreCase(this.command)) {
diff --git a/luminol-server/minecraft-patches/features/0013-Add-fix-for-off-region-adult-following-ai-behavior.patch b/luminol-server/minecraft-patches/features/0013-Add-fix-for-off-region-adult-following-ai-behavior.patch
new file mode 100644
index 0000000..48f64a1
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0013-Add-fix-for-off-region-adult-following-ai-behavior.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:39:35 +0800
+Subject: [PATCH] Add fix for off region adult following ai behavior
+
+
+diff --git a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
+index a9be3acbf4ea52d2988347abfa6f4f8c02b1da26..751f3dde8e6bc2c0365e8672f5079af0379a69de 100644
+--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
++++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
+@@ -25,6 +25,14 @@ public class BabyFollowAdult {
+ return false;
+ } else {
+ LivingEntity ageableMob = instance.get(nearestVisibleAdult); // CraftBukkit - type
++
++ // Luminol start - Fix off world entity following which caused async issue
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(ageableMob)) {
++ nearestVisibleAdult.erase();
++ return true;
++ }
++ // Luminol end
++
+ if (mob.closerThan(ageableMob, followRange.getMaxValue() + 1) && !mob.closerThan(ageableMob, followRange.getMinValue())) {
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(mob, ageableMob, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER);
diff --git a/luminol-server/minecraft-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch b/luminol-server/minecraft-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch
new file mode 100644
index 0000000..d1da7f4
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch
@@ -0,0 +1,372 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:49:22 +0800
+Subject: [PATCH] Add configurable region format framework & linear v2 region
+ format support
+
+
+diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
+index a814512fcfb85312474ae2c2c21443843bf57831..2e084a5b28cbe4737f48c25e10af589213525362 100644
+--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
++++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
+@@ -8,9 +8,9 @@ public interface ChunkSystemRegionFileStorage {
+
+ public boolean moonrise$doesRegionFileNotExistNoIO(final int chunkX, final int chunkZ);
+
+- public RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ);
++ public abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // Luminol - Configurable region file format
+
+- public RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException;
++ public abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // Luminol - Configurable region file format
+
+ public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(
+ final int chunkX, final int chunkZ, final CompoundTag compound
+diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+index 1acea58838f057ab87efd103cbecb6f5aeaef393..224538fc0a009db341588ff7ebe32b58aa003ed0 100644
+--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
++++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+@@ -1462,7 +1462,7 @@ public final class MoonriseRegionFileIO {
+
+ public static interface IORunnable {
+
+- public void run(final RegionFile regionFile) throws IOException;
++ public void run(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
+
+ }
+ }
+diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
+index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d5815c8c1 100644
+--- a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
++++ b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
+@@ -8,5 +8,5 @@ public interface ChunkSystemChunkBuffer {
+
+ public void moonrise$setWriteOnClose(final boolean value);
+
+- public void moonrise$write(final RegionFile regionFile) throws IOException;
++ public void moonrise$write(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
+ }
+diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
+index 46375fa81b36b89b79c22f0a7ac6d610ab1183d4..c00378ba258647787bb9138e319b0f6a0b00e1ed 100644
+--- a/net/minecraft/server/MinecraftServer.java
++++ b/net/minecraft/server/MinecraftServer.java
+@@ -986,10 +986,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap<>());
+ volatile Component status = Component.translatable("optimizeWorld.stage.counting");
+- static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
++ static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\\\"+ net.minecraft.world.level.chunk.storage.RegionFileStorage.getExtensionName() +"$"); // Luminol - Configurable region file format
+ final DimensionDataStorage overworldDataStorage;
+
+ public WorldUpgrader(
+@@ -261,7 +261,7 @@ public class WorldUpgrader implements AutoCloseable {
+ }
+
+ private static List getAllChunkPositions(RegionStorageInfo regionStorageInfo, Path path) {
+- File[] files = path.toFile().listFiles((directory, filename) -> filename.endsWith(".mca"));
++ File[] files = path.toFile().listFiles((directory, filename) -> filename.endsWith(net.minecraft.world.level.chunk.storage.RegionFileStorage.getExtensionName())); // Luminol - Configurable region file format
+ if (files == null) {
+ return List.of();
+ } else {
+@@ -274,7 +274,7 @@ public class WorldUpgrader implements AutoCloseable {
+ int i1 = Integer.parseInt(matcher.group(2)) << 5;
+ List list1 = Lists.newArrayList();
+
+- try (RegionFile regionFile = new RegionFile(regionStorageInfo, file.toPath(), path, true)) {
++ try (abomination.IRegionFile regionFile = net.minecraft.world.level.chunk.storage.RegionFileStorage.createNew(regionStorageInfo, file.toPath(), path, true)) { // Luminol - Configurable region file format
+ for (int i2 = 0; i2 < 32; i2++) {
+ for (int i3 = 0; i3 < 32; i3++) {
+ ChunkPos chunkPos = new ChunkPos(i2 + i, i3 + i1);
+@@ -322,7 +322,7 @@ public class WorldUpgrader implements AutoCloseable {
+
+ protected abstract boolean tryProcessOnePosition(T chunkStorage, ChunkPos chunkPos, ResourceKey dimension);
+
+- private void onFileFinished(RegionFile regionFile) {
++ private void onFileFinished(abomination.IRegionFile regionFile) { // Luminol - Configurable region file format
+ if (WorldUpgrader.this.recreateRegionFiles) {
+ if (this.previousWriteFuture != null) {
+ this.previousWriteFuture.join();
+@@ -424,7 +424,7 @@ public class WorldUpgrader implements AutoCloseable {
+ }
+ }
+
+- record FileToUpgrade(RegionFile file, List chunksToUpgrade) {
++ record FileToUpgrade(abomination.IRegionFile file, List chunksToUpgrade) { // Luminol - Configurable region file format
+ }
+
+ class PoiUpgrader extends WorldUpgrader.SimpleRegionStorageUpgrader {
+diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
+index 0c41177462cca5c4bbab6490e323b9535fd6300f..39b3c3ca7248fe60833f04aee89c8851b21d5008 100644
+--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
++++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
+@@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler;
+ import net.minecraft.world.level.ChunkPos;
+ import org.slf4j.Logger;
+
+-public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
++public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile , abomination.IRegionFile{ // Paper - rewrite chunk system // Luminol - Configurable region file format
+ private static final Logger LOGGER = LogUtils.getLogger();
+ public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
+ private static final int SECTOR_BYTES = 4096;
+@@ -124,7 +124,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
+ }
+
+ // note: only call for CHUNK regionfiles
+- boolean recalculateHeader() throws IOException {
++ public boolean recalculateHeader() throws IOException { // Luminol - Configurable region file format // Luminol - Configurable region file format
+ if (!this.canRecalcHeader) {
+ return false;
+ }
+@@ -786,7 +786,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
+ }
+ }
+
+- protected synchronized void write(ChunkPos chunkPos, ByteBuffer chunkData) throws IOException {
++ public synchronized void write(ChunkPos chunkPos, ByteBuffer chunkData) throws IOException { // Luminol - Configurable region file format
+ int offsetIndex = getOffsetIndex(chunkPos);
+ int i = this.offsets.get(offsetIndex);
+ int sectorNumber = getSectorNumber(i);
+@@ -904,7 +904,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
+ }
+
+ @Override
+- public final void moonrise$write(final RegionFile regionFile) throws IOException {
++ public final void moonrise$write(final abomination.IRegionFile regionFile) throws IOException { // Luminol - Configurable region file format
+ regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count));
+ }
+ // Paper end - rewrite chunk system
+@@ -970,11 +970,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
+ return (x & 31) + (z & 31) * 32;
+ }
+
+- synchronized boolean isOversized(int x, int z) {
++ public synchronized boolean isOversized(int x, int z) { // Luminol - Configurable region file format
+ return this.oversized[getChunkIndex(x, z)] == 1;
+ }
+
+- synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
++ public synchronized void setOversized(int x, int z, boolean oversized) throws IOException { // Luminol - Configurable region file format
+ final int offset = getChunkIndex(x, z);
+ boolean previous = this.oversized[offset] == 1;
+ this.oversized[offset] = (byte) (oversized ? 1 : 0);
+@@ -1013,7 +1013,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
+ return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
+ }
+
+- synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException {
++ public synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException { // Luminol - Configurable region file format
+ Path file = getOversizedFile(x, z);
+ try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new java.util.zip.InflaterInputStream(Files.newInputStream(file))))) {
+ return net.minecraft.nbt.NbtIo.read((java.io.DataInput) out);
+diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..437fff55b565e469f6a4e41288b6f805e125be60 100644
+--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+@@ -18,7 +18,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
+ public static final String ANVIL_EXTENSION = ".mca";
+ private static final int MAX_CACHE_SIZE = 256;
+- public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap<>();
++ public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap<>(); // Luminol - Configurable region file format
+ private final RegionStorageInfo info;
+ private final Path folder;
+ private final boolean sync;
+@@ -33,7 +33,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ @Nullable
+ public static ChunkPos getRegionFileCoordinates(Path file) {
+ String fileName = file.getFileName().toString();
+- if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) {
++ if (!fileName.startsWith("r.") || !fileName.endsWith(getExtensionName())) { // Luminol - Configurable region file format
+ return null;
+ }
+
+@@ -58,8 +58,27 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ private static final int MAX_NON_EXISTING_CACHE = 1024 * 4;
+ private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
+ private static String getRegionFileName(final int chunkX, final int chunkZ) {
+- return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".mca";
++ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + getExtensionName(); // Luminol - Configurable region file format
+ }
++ // Luminol start - Configurable region file format
++ public static abomination.IRegionFile createNew(RegionStorageInfo info, Path filePath, Path folder, boolean sync) throws IOException{
++ final me.earthme.luminol.utils.EnumRegionFormat regionFormat = me.earthme.luminol.config.modules.misc.RegionFormatConfig.regionFormat;
++ final String fullFileName = filePath.getFileName().toString();
++ final String[] fullNameSplit = fullFileName.split("\\.");
++ final String extensionName = fullNameSplit[fullNameSplit.length - 1];
++
++ if (!regionFormat.getArgument().equalsIgnoreCase(extensionName)) {
++ net.minecraft.server.MinecraftServer.setFatalException(new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument()));
++ throw new IOException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
++ }
++
++ return regionFormat.getCreator().create(new me.earthme.luminol.utils.RegionCreatorInfo(info, filePath, folder, sync));
++ }
++
++ public static String getExtensionName() {
++ return "." + me.earthme.luminol.config.modules.misc.RegionFormatConfig.regionFormat.getArgument();
++ }
++ // Luminol end
+
+ private boolean doesRegionFilePossiblyExist(final long position) {
+ synchronized (this.nonExistingRegionFiles) {
+@@ -93,15 +112,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ }
+
+ @Override
+- public synchronized final RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) {
++ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // Luminol - Configurable region file format
+ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT));
+ }
+
+ @Override
+- public synchronized final RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException {
++ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // Luminol - Configurable region file format
+ final long key = ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
+
+- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
++ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
+ if (ret != null) {
+ return ret;
+ }
+@@ -125,7 +144,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+
+ FileUtil.createDirectoriesSafe(this.folder);
+
+- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
++ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
+
+ this.regionCache.putAndMoveToFirst(key, ret);
+
+@@ -144,7 +163,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ }
+
+ final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
+- final RegionFile regionFile = this.getRegionFile(pos);
++ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
+
+ // note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
+ // (and, the regionfile parameter is unused for writing until the write call)
+@@ -178,7 +197,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ ) throws IOException {
+ final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
+ if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
+- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
++ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
+ if (regionFile != null) {
+ regionFile.clear(pos);
+ } // else: didn't exist
+@@ -193,7 +212,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.ReadData moonrise$readData(
+ final int chunkX, final int chunkZ
+ ) throws IOException {
+- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
++ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
+
+ final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
+
+@@ -237,7 +256,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ }
+ // Paper end - rewrite chunk system
+ // Paper start - rewrite chunk system
+- public RegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException {
++ public abomination.IRegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException { // Luminol - Configurable region file format
+ return this.getRegionFile(chunkcoordintpair, false);
+ }
+ // Paper end - rewrite chunk system
+@@ -249,7 +268,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers
+ }
+
+- @org.jetbrains.annotations.Contract("_, false -> !null") @Nullable private RegionFile getRegionFile(ChunkPos chunkPos, boolean existingOnly) throws IOException { // CraftBukkit
++ @org.jetbrains.annotations.Contract("_, false -> !null") @Nullable private abomination.IRegionFile getRegionFile(ChunkPos chunkPos, boolean existingOnly) throws IOException { // CraftBukkit
+ // Paper start - rewrite chunk system
+ if (existingOnly) {
+ return this.moonrise$getRegionFileIfExists(chunkPos.x, chunkPos.z);
+@@ -257,7 +276,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ synchronized (this) {
+ final long key = ChunkPos.asLong(chunkPos.x >> REGION_SHIFT, chunkPos.z >> REGION_SHIFT);
+
+- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
++ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
+ if (ret != null) {
+ return ret;
+ }
+@@ -272,7 +291,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+
+ FileUtil.createDirectoriesSafe(this.folder);
+
+- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
++ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
+
+ this.regionCache.putAndMoveToFirst(key, ret);
+
+@@ -286,7 +305,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
+ }
+
+- private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
++ private static CompoundTag readOversizedChunk(abomination.IRegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // Luminol - Configurable region file format
+ synchronized (regionfile) {
+ try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
+ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
+@@ -321,7 +340,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ @Nullable
+ public CompoundTag read(ChunkPos chunkPos) throws IOException {
+ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
+- RegionFile regionFile = this.getRegionFile(chunkPos, true);
++ abomination.IRegionFile regionFile = this.getRegionFile(chunkPos, true); // Luminol - Configurable region file format
+ if (regionFile == null) {
+ return null;
+ }
+@@ -360,7 +379,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+
+ public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException {
+ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
+- RegionFile regionFile = this.getRegionFile(chunkPos, true);
++ abomination.IRegionFile regionFile = this.getRegionFile(chunkPos, true); // Luminol - Configurable region file format
+ if (regionFile == null) {
+ return;
+ }
+@@ -374,7 +393,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ }
+
+ public void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { // Paper - rewrite chunk system - public
+- RegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system
++ abomination.IRegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system // Luminol - Configurable region file format
+ // Paper start - rewrite chunk system
+ if (regionFile == null) {
+ // if the RegionFile doesn't exist, no point in deleting from it
+@@ -404,7 +423,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ // Paper start - rewrite chunk system
+ synchronized (this) {
+ final ExceptionCollector exceptionCollector = new ExceptionCollector<>();
+- for (final RegionFile regionFile : this.regionCache.values()) {
++ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
+ try {
+ regionFile.close();
+ } catch (final IOException ex) {
+@@ -420,7 +439,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ // Paper start - rewrite chunk system
+ synchronized (this) {
+ final ExceptionCollector exceptionCollector = new ExceptionCollector<>();
+- for (final RegionFile regionFile : this.regionCache.values()) {
++ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
+ try {
+ regionFile.flush();
+ } catch (final IOException ex) {
diff --git a/luminol-server/minecraft-patches/features/0015-Add-config-for-watchdog-timeout.patch b/luminol-server/minecraft-patches/features/0015-Add-config-for-watchdog-timeout.patch
new file mode 100644
index 0000000..36e65d7
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0015-Add-config-for-watchdog-timeout.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:51:21 +0800
+Subject: [PATCH] Add config for watchdog timeout
+
+
+diff --git a/io/papermc/paper/threadedregions/FoliaWatchdogThread.java b/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
+index 258d82ab2c78482e1561343e8e1f81fc33f1895e..967107c0f4a18a29877883ccddb4d7962f4b5788 100644
+--- a/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
++++ b/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
+@@ -65,7 +65,7 @@ public final class FoliaWatchdogThread extends Thread {
+
+ for (final RunningTick tick : ticks) {
+ final long elapsed = now - tick.lastPrint;
+- if (elapsed <= TimeUnit.SECONDS.toNanos(5L)) {
++ if (elapsed <= TimeUnit.MILLISECONDS.toNanos(me.earthme.luminol.config.modules.misc.FoliaWatchogConfig.tickRegionTimeOutMs)) { // Luminol - Add config for watchdog timeout
+ continue;
+ }
+ tick.lastPrint = now;
diff --git a/luminol-server/minecraft-patches/features/0016-Try-fixing-folia-spector-teleportation.patch b/luminol-server/minecraft-patches/features/0016-Try-fixing-folia-spector-teleportation.patch
new file mode 100644
index 0000000..1c929ec
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0016-Try-fixing-folia-spector-teleportation.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:53:24 +0800
+Subject: [PATCH] Try fixing folia spector teleportation
+
+
+diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
+index b4a4eec6029f1aee5f3b0da6938a9b23db36d5f9..57f30de55968046a9ac053fe5052bf4070f87e44 100644
+--- a/net/minecraft/server/level/ServerPlayer.java
++++ b/net/minecraft/server/level/ServerPlayer.java
+@@ -975,8 +975,24 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
+ }
+
+ Entity camera = this.getCamera();
++ //Luminol start - Fix folia spector teleportation
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(camera) && me.earthme.luminol.config.modules.fixes.FoliaSpectorTeleportationFixConfig.fixSpectorTeleportFolia){
++ this.setCamera(this);
++ }
++ //Luminol end
++
+ if (camera != this) {
+- if (camera.isAlive()) {
++ // Luminol start - Fix folia spector teleportation
++ var flag = false;
++ var cameraPos = camera.blockPosition();
++ var cameraLevel = camera.level();
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(cameraLevel, cameraPos) && me.earthme.luminol.config.modules.fixes.FoliaSpectorTeleportationFixConfig.fixSpectorTeleportFolia){
++ this.setCamera(this);
++ flag = true;
++ }
++ // Luminol end
++
++ if (camera.isAlive() && !flag) { // Luminol - Fix folia spector teleportation
+ this.absMoveTo(camera.getX(), camera.getY(), camera.getZ(), camera.getYRot(), camera.getXRot());
+ this.serverLevel().getChunkSource().move(this);
+ if (this.wantsToStopRiding()) {
diff --git a/patches/server/0022-Teleport-async-if-entity-was-moving-to-another-regio.patch b/luminol-server/minecraft-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch
similarity index 53%
rename from patches/server/0022-Teleport-async-if-entity-was-moving-to-another-regio.patch
rename to luminol-server/minecraft-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch
index adf6acb..b576462 100644
--- a/patches/server/0022-Teleport-async-if-entity-was-moving-to-another-regio.patch
+++ b/luminol-server/minecraft-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch
@@ -1,48 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 30 Nov 2024 11:36:43 +0800
+Date: Sun, 12 Jan 2025 10:53:41 +0800
Subject: [PATCH] Teleport async if entity was moving to another region at once
-diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0e51d465db3554ac80d00c6b85cc1f013f3949ba
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java
-@@ -0,0 +1,28 @@
-+package me.earthme.luminol.config.modules.fixes;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class FoliaEntityMovingFixConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled", comments =
-+ """
-+ A simple fix of a issue on folia\s
-+ (Some times 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""")
-+ public static boolean enabled = false;
-+ @ConfigInfo(baseName = "warn_on_detected")
-+ public static boolean warnOnDetected = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.FIXES;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "folia.fix_high_velocity_issue";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 8e1a75e56cc373a9ec9b563666af0864eee99479..4fdbdd1c5c937c20026afe555fa1c8371b4eaa16 100644
---- a/src/main/java/net/minecraft/world/entity/Entity.java
-+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -1181,6 +1181,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
+index 4cfc228a60a147409b8afc4cb138ce6437a9b667..c87db2d497ca9ed2e8aad5f1bc52555ff0952b80 100644
+--- a/net/minecraft/world/entity/Entity.java
++++ b/net/minecraft/world/entity/Entity.java
+@@ -1099,6 +1099,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Paper end - detailed watchdog information
@@ -53,7 +19,7 @@ index 8e1a75e56cc373a9ec9b563666af0864eee99479..4fdbdd1c5c937c20026afe555fa1c837
public void move(MoverType type, Vec3 movement) {
final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity
// Paper start - detailed watchdog information
-@@ -1191,6 +1195,32 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -1109,6 +1113,32 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.moveStartZ = this.getZ();
this.moveVector = movement;
}
@@ -70,7 +36,7 @@ index 8e1a75e56cc373a9ec9b563666af0864eee99479..4fdbdd1c5c937c20026afe555fa1c837
+ (ServerLevel) this.level(),
+ finalPosition,
+ this.getYRot(), this.getXRot(),
-+ null, PlayerTeleportEvent.TeleportCause.UNKNOWN,
++ null, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN,
+ Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS,
+ result -> {
+ this.preventMoving = false;
diff --git a/luminol-server/minecraft-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch b/luminol-server/minecraft-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch
new file mode 100644
index 0000000..f187408
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch
@@ -0,0 +1,58 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:56:59 +0800
+Subject: [PATCH] Try fixing folia off region POI accessing issue
+
+
+diff --git a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
+index 3614551856c594f3c0cfee984fcf03fad672b007..d97aa31ddffc19f7ca2cd556d5ec3373a17055cf 100644
+--- a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
++++ b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
+@@ -47,10 +47,17 @@ public class GoToPotentialJobSite extends Behavior {
+ ServerLevel level1 = level.getServer().getLevel(globalPos.dimension());
+ if (level1 != null) {
+ PoiManager poiManager = level1.getPoiManager();
++ //Luminol start - Fix off region POI accessing
++ java.lang.Runnable scheduledRelease = () -> {
+ if (poiManager.exists(blockPos, holder -> true)) {
+ poiManager.release(blockPos);
+ }
+-
++ };
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(level1, blockPos) && me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled)
++ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(level, blockPos.getX() >> 4, blockPos.getZ() >> 4, scheduledRelease);
++ else
++ scheduledRelease.run();
++ //Luminol end
+ DebugPackets.sendPoiTicketCountPacket(level, blockPos);
+ }
+ });
+diff --git a/net/minecraft/world/entity/ai/behavior/YieldJobSite.java b/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
+index 37ad79e201e36a1a9520219e3faa4dcffa7b4dfd..d301614a254ea7a453a226272ab1c3aa0117fbfa 100644
+--- a/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
++++ b/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
+@@ -33,7 +33,10 @@ public class YieldJobSite {
+ } else if (villager.getVillagerData().getProfession() != VillagerProfession.NONE) {
+ return false;
+ } else {
+- BlockPos blockPos = instance.get(potentialJobSite).pos();
++ final GlobalPos globalPos = instance.get(potentialJobSite); //Luminol - Try fixing off main POI accessing
++ final net.minecraft.server.level.ServerLevel targetLevel = net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension()); //Luminol - Try fixing off main POI accessing
++ BlockPos blockPos = globalPos.pos(); //Luminol - Try fixing off main POI accessing
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(targetLevel, blockPos) && me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled) return true; //Luminol - Try fixing off main POI accessing
+ Optional> type = level.getPoiManager().getType(blockPos);
+ if (type.isEmpty()) {
+ return true;
+diff --git a/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+index c10810bf00d75f459c3c6a9415c1e09f0519d50e..3adafa43367cd6648ecbccb92ba5bd509740d5a4 100644
+--- a/net/minecraft/world/entity/ai/village/poi/PoiManager.java
++++ b/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+@@ -212,7 +212,7 @@ public class PoiManager extends SectionStorage im
+
+ public Stream getInSquare(Predicate> typePredicate, BlockPos pos, int distance, PoiManager.Occupancy status) {
+ int i = Math.floorDiv(distance, 16) + 1;
+- return ChunkPos.rangeClosed(new ChunkPos(pos), i).flatMap(chunkPos -> this.getInChunk(typePredicate, chunkPos, status)).filter(poiRecord -> {
++ return ChunkPos.rangeClosed(new ChunkPos(pos), i).filter(cpos -> me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled ? ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.world,cpos) : true).flatMap(chunkPos -> this.getInChunk(typePredicate, chunkPos, status)).filter(poiRecord -> { // Luminol - Fix off region POI access
+ BlockPos pos1 = poiRecord.getPos();
+ return Math.abs(pos1.getX() - pos.getX()) <= distance && Math.abs(pos1.getZ() - pos.getZ()) <= distance;
+ });
diff --git a/patches/server/0024-Try-fixing-folia-315.patch b/luminol-server/minecraft-patches/features/0019-Try-fixing-folia-315.patch
similarity index 57%
rename from patches/server/0024-Try-fixing-folia-315.patch
rename to luminol-server/minecraft-patches/features/0019-Try-fixing-folia-315.patch
index 4316a18..3f39ee4 100644
--- a/patches/server/0024-Try-fixing-folia-315.patch
+++ b/luminol-server/minecraft-patches/features/0019-Try-fixing-folia-315.patch
@@ -1,15 +1,15 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 11 Jan 2025 15:23:31 +0800
+Date: Sun, 12 Jan 2025 10:58:43 +0800
Subject: [PATCH] Try fixing folia #315
Might be useful to https://github.com/PaperMC/Folia/issues/315
-diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
-index 3bd0f3ae53eaa22409152d7f41e511e76bdaa265..6e76e4801653d0c84cb811bf72f1e1e8e1712ff6 100644
---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
-+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
-@@ -51,7 +51,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
+diff --git a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+index 12e563b04e6afcd227f3ef6cbdfcedf59be9509e..e76bc2c0c72e40267649e260da9bed750a450612 100644
+--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+@@ -43,7 +43,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
return Items.ENDER_PEARL;
}
@@ -18,15 +18,15 @@ index 3bd0f3ae53eaa22409152d7f41e511e76bdaa265..6e76e4801653d0c84cb811bf72f1e1e8
protected void setOwnerThroughUUID(UUID uuid) {
this.deregisterFromCurrentOwner();
super.setOwnerThroughUUID(uuid);
-@@ -64,6 +64,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
- super.setOwner(entity);
+@@ -56,6 +56,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
+ super.setOwner(owner);
this.registerToCurrentOwner();
}
+ */ // Luminol - Try fixing folia #315
private void deregisterFromCurrentOwner() {
- Entity entity = this.getOwner();
-@@ -388,7 +389,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
+ if (this.getOwner() instanceof ServerPlayer serverPlayer) {
+@@ -342,7 +343,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
@Override
public void onRemoval(Entity.RemovalReason reason) {
if (reason != Entity.RemovalReason.UNLOADED_WITH_PLAYER) {
diff --git a/luminol-server/minecraft-patches/features/0020-Force-disable-builtin-spark-plugin.patch b/luminol-server/minecraft-patches/features/0020-Force-disable-builtin-spark-plugin.patch
new file mode 100644
index 0000000..b185cc2
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0020-Force-disable-builtin-spark-plugin.patch
@@ -0,0 +1,98 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:00:49 +0800
+Subject: [PATCH] Force disable builtin spark plugin
+
+
+diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
+index c00378ba258647787bb9138e319b0f6a0b00e1ed..ff71466ec0848d16121e351e30c31bb419af8b99 100644
+--- a/net/minecraft/server/MinecraftServer.java
++++ b/net/minecraft/server/MinecraftServer.java
+@@ -783,8 +783,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= i) {
+- this.server.spark.tickStart(); // Paper - spark
++ if (false) this.server.spark.tickStart(); // Paper - spark // Luminol - Force disable builtin spark
+ if (this.emptyTicks == i) {
+ LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhileEmptySeconds());
+ this.autoSave();
+@@ -1612,7 +1612,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
+Date: Sun, 12 Jan 2025 11:02:06 +0800
+Subject: [PATCH] Set old pos before moving entity by piston
+
+
+diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+index 3df23feff6937b6a2dbeff82e489a9a4ff644843..5d98069b61df57792e6b0cab809f2996b7d45c88 100644
+--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
++++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+@@ -195,6 +195,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
+
+ private static void moveEntityByPiston(Direction noClipDirection, Entity entity, double progress, Direction direction) {
+ NOCLIP.set(noClipDirection);
++ if (me.earthme.luminol.config.modules.fixes.FoliaPistonIssueFixConfig.enabled) entity.setOldPosAndRot(); // Luminol- Try fixing folia issue #311
+ entity.move(MoverType.PISTON, new Vec3(progress * direction.getStepX(), progress * direction.getStepY(), progress * direction.getStepZ()));
+ entity.applyEffectsFromBlocks();
+ NOCLIP.set(null);
diff --git a/luminol-server/minecraft-patches/features/0022-Merge-Paper-11945-for-temporary-hooper-behavior-fix.patch b/luminol-server/minecraft-patches/features/0022-Merge-Paper-11945-for-temporary-hooper-behavior-fix.patch
new file mode 100644
index 0000000..17292f3
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0022-Merge-Paper-11945-for-temporary-hooper-behavior-fix.patch
@@ -0,0 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:03:09 +0800
+Subject: [PATCH] Merge Paper #11945 for temporary hooper behavior fix
+
+A hopper optimization fix on Paper's pr : https://github.com/PaperMC/Paper/pull/11945
+
+diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+index ae988c4910421fb720177178ef6136e595ae6946..72a81e29be6570fb119b159210453a86f003f893 100644
+--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
++++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+@@ -698,6 +698,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+ } else if (canMergeItems(item, stack)) {
+ int i = Math.min(stack.getMaxStackSize(), destination.getMaxStackSize()) - item.getCount(); // Paper - Make hoppers respect inventory max stack size
+ int min = Math.min(stack.getCount(), i);
++ stack = stack.copy(true); // Luminol
+ stack.shrink(min);
+ item.grow(min);
+ flag = min > 0;
diff --git a/luminol-server/minecraft-patches/features/0023-Kaiiju-Don-t-pathfind-outside-region.patch b/luminol-server/minecraft-patches/features/0023-Kaiiju-Don-t-pathfind-outside-region.patch
new file mode 100644
index 0000000..fd72f61
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0023-Kaiiju-Don-t-pathfind-outside-region.patch
@@ -0,0 +1,20 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:03:59 +0800
+Subject: [PATCH] Kaiiju Don't pathfind outside region
+
+
+diff --git a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
+index 621ba76784f2b92790eca62be4d0688834335ab6..52b3f1795843f40fdb3298cfd1a570a211a08739 100644
+--- a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
++++ b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
+@@ -119,7 +119,9 @@ public class MoveToTargetSink extends Behavior {
+
+ private boolean tryComputePath(Mob mob, WalkTarget target, long time) {
+ BlockPos blockPos = target.getTarget().currentBlockPosition();
++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(mob.level(), blockPos)) // Kaiiju - Don't pathfind outside region
+ this.path = mob.getNavigation().createPath(blockPos, 0);
++ else this.path = null; // Kaiiju - Don't pathfind outside region
+ this.speedModifier = target.getSpeedModifier();
+ Brain> brain = mob.getBrain();
+ if (this.reachedTarget(mob, target)) {
diff --git a/patches/server/0029-Kaiiju-Vanilla-end-portal-teleportation.patch b/luminol-server/minecraft-patches/features/0024-Kaiiju-Vanilla-end-portal-teleportation.patch
similarity index 85%
rename from patches/server/0029-Kaiiju-Vanilla-end-portal-teleportation.patch
rename to luminol-server/minecraft-patches/features/0024-Kaiiju-Vanilla-end-portal-teleportation.patch
index 84ef6fe..33edb84 100644
--- a/patches/server/0029-Kaiiju-Vanilla-end-portal-teleportation.patch
+++ b/luminol-server/minecraft-patches/features/0024-Kaiiju-Vanilla-end-portal-teleportation.patch
@@ -1,14 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 30 Nov 2024 11:48:36 +0800
+Date: Sun, 12 Jan 2025 11:04:12 +0800
Subject: [PATCH] Kaiiju Vanilla end portal teleportation
-diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..64e081f993c2c844f83af227380b8a957eaabad4 100644
---- a/src/main/java/net/minecraft/world/entity/Entity.java
-+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -114,6 +114,7 @@ import net.minecraft.world.level.block.Rotation;
+diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
+index c87db2d497ca9ed2e8aad5f1bc52555ff0952b80..88ca22ed6af613370ca8691ad9ebeb113e1637fe 100644
+--- a/net/minecraft/world/entity/Entity.java
++++ b/net/minecraft/world/entity/Entity.java
+@@ -110,6 +110,7 @@ import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.border.WorldBorder;
@@ -16,7 +16,7 @@ index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..64e081f993c2c844f83af227380b8a95
import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntityInLevelCallback;
import net.minecraft.world.level.gameevent.DynamicGameEventListener;
-@@ -4458,13 +4459,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4265,13 +4266,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
targetPos, 16, // load 16 blocks to be safe from block physics
ca.spottedleaf.concurrentutil.util.Priority.HIGH,
(chunks) -> {
@@ -37,7 +37,7 @@ index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..64e081f993c2c844f83af227380b8a95
TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET),
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL
)
-@@ -4660,6 +4666,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4467,6 +4473,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (!this.canPortalAsync(destination, takePassengers)) {
return false;
}
@@ -48,7 +48,7 @@ index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..64e081f993c2c844f83af227380b8a95
Vec3 initialPosition = this.position();
ChunkPos initialPositionChunk = new ChunkPos(
-@@ -4724,9 +4734,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4531,9 +4541,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
info.postTeleportTransition().onTransition(teleported);
}
diff --git a/luminol-server/minecraft-patches/features/0025-Kaiiju-Entity-tick-and-removal-limiter.patch b/luminol-server/minecraft-patches/features/0025-Kaiiju-Entity-tick-and-removal-limiter.patch
new file mode 100644
index 0000000..88c2db8
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0025-Kaiiju-Entity-tick-and-removal-limiter.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:07:08 +0800
+Subject: [PATCH] Kaiiju Entity tick and removal limiter
+
+
+diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
+index c6e487a4c14e6b82533881d01f32349b9ae28728..2c747cb8a724cd25c9d724908f92b320741600de 100644
+--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
++++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
+@@ -354,6 +354,7 @@ public final class RegionizedWorldData {
+ private final IteratorSafeOrderedReferenceSet navigatingMobs = new IteratorSafeOrderedReferenceSet<>();
+ public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
+ public final ReferenceList trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
++ public final dev.kaiijumc.kaiiju.KaiijuEntityThrottler entityThrottler = new dev.kaiijumc.kaiiju.KaiijuEntityThrottler(); // Kaiiju
+
+ // block ticking
+ private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>();
+diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
+index 0cc5607080f79f9e9b65606a3e16fd4961368b02..4c7b0582c7989138ada14e31dc76b8310c7c6f40 100644
+--- a/net/minecraft/server/level/ServerLevel.java
++++ b/net/minecraft/server/level/ServerLevel.java
+@@ -808,6 +808,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ }
+
+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); try { // Folia - profiler
++ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterStart(); // Kaiiju
+ io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); } // Folia - profiler
+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); try { // Folia - profiler
+@@ -829,6 +830,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+
+ entity.stopRiding();
+ }
++ // Kaiiju start
++ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) {
++ dev.kaiijumc.kaiiju.KaiijuEntityThrottler.EntityThrottlerReturn throttle = regionizedWorldData.entityThrottler.tickLimiterShouldSkip(entity);
++ if (throttle.remove && !entity.hasCustomName()) entity.remove(Entity.RemovalReason.DISCARDED);
++ if (throttle.skip) return;
++ }
++ // Kaiiju end
+
+ profilerFiller.push("tick");
+ this.guardEntityTick(this::tickNonPassenger, entity);
+@@ -838,6 +846,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ }
+ }
+ );
++ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterFinish(regionizedWorldData); // Kaiiju
+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); } // Folia - profiler
+ profilerFiller.pop();
+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY); try { // Folia - profiler
diff --git a/luminol-server/minecraft-patches/features/0026-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch b/luminol-server/minecraft-patches/features/0026-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch
new file mode 100644
index 0000000..389f266
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0026-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch
@@ -0,0 +1,313 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:29:49 +0800
+Subject: [PATCH] KioCG Chunk API and display of chunkhot in tpsbar
+
+
+diff --git a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
+index 8d67b4629c69d3039b199aaad45533d1acde114e..f7bfeca4b11b9860241d5eb80b6df420868c7bea 100644
+--- a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
++++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
+@@ -136,6 +136,7 @@ public abstract class BaseChunkSystemHooks implements ca.spottedleaf.moonrise.co
+
+ @Override
+ public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
++ chunk.getChunkHot().clear(); // KioCG
+ chunk.getLevel().getCurrentWorldData().removeTickingChunk(chunk.moonrise$getChunkAndHolder()); // Folia - region threading
+ ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
+ }
+diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
+index ff71466ec0848d16121e351e30c31bb419af8b99..330af9f4de1c72387326816065350e71fe546efe 100644
+--- a/net/minecraft/server/MinecraftServer.java
++++ b/net/minecraft/server/MinecraftServer.java
+@@ -1666,7 +1666,44 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop chunks = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>();
++ if (region != null){
++ for (net.minecraft.server.level.ServerChunkCache.ChunkAndHolder chunkAndHolder : region.world.getCurrentWorldData().getTickingChunks()){
++ final net.minecraft.world.level.chunk.LevelChunk chunk = chunkAndHolder.chunk();
++
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(region.world, chunk.locX, chunk.locZ)){
++ continue;
++ }
++
++ chunks.add(chunk);
++ }
++ }
++ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
++ final java.util.Iterator chunkIterator = chunks.unsafeIterator();
++ while (chunkIterator.hasNext()){
++ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
++
++ targetChunk.getChunkHot().nextTick();
++ targetChunk.getChunkHot().start();
++ }
++ }
++ //KioCG end
+ this.tickChildren(hasTimeLeft, region); // Folia - region threading
++ // KioCG start - ChunkHot
++ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
++ final java.util.Iterator chunkIterator = chunks.unsafeIterator();
++ while (chunkIterator.hasNext()){
++ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
++
++ if (!targetChunk.getChunkHot().isStarted()){
++ continue;
++ }
++
++ targetChunk.getChunkHot().stop();
++ }
++ }
++ //KioCG end
+ if (false && nanos - this.lastServerStatus >= STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading
+ this.lastServerStatus = nanos;
+ this.status = this.buildServerStatus();
+diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
+index 4c7b0582c7989138ada14e31dc76b8310c7c6f40..0eece9a417aa28de36be2c932eed7434bbb8b961 100644
+--- a/net/minecraft/server/level/ServerLevel.java
++++ b/net/minecraft/server/level/ServerLevel.java
+@@ -1347,6 +1347,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ final int timerId = isActive ? entity.getType().tickTimerId : entity.getType().inactiveTickTimerId;
+ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler();
+ profiler.startTimer(timerId);
++ LevelChunk levelChunk = entity.shouldTickHot() ? this.getChunkIfLoaded(entity.moonrise$getSectionX(),entity.moonrise$getSectionZ()) : null; // KioCG
++ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
+ try {
+ // Folia end - profiler
+ if (isActive) { // Paper - EAR 2
+@@ -1364,6 +1366,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ } else {entity.inactiveTick();} // Paper - EAR 2
+ profilerFiller.pop();
+ } finally { profiler.stopTimer(timerId); } // Folia - profiler
++ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
+
+ for (Entity entity1 : entity.getPassengers()) {
+ this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2
+@@ -1383,6 +1386,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ final int timerId = isActive ? passengerEntity.getType().tickTimerId : passengerEntity.getType().inactiveTickTimerId;
+ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler();
+ profiler.startTimer(timerId);
++ LevelChunk levelChunk = !(passengerEntity instanceof Player) ? this.getChunkIfLoaded(passengerEntity.blockPosition()) : null; // KioCG
++ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
+ try {
+ // Folia end - profiler
+ passengerEntity.setOldPosAndRot();
+@@ -1416,6 +1421,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ this.tickPassenger(passengerEntity, entity, isActive); // Paper - EAR 2
+ }
+ } finally { profiler.stopTimer(timerId); } // Folia - profiler
++ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
+ }
+ }
+
+diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
+index 57f30de55968046a9ac053fe5052bf4070f87e44..f24c9a593a6b7e664a91ec1a132dd74fbbd20bc6 100644
+--- a/net/minecraft/server/level/ServerPlayer.java
++++ b/net/minecraft/server/level/ServerPlayer.java
+@@ -1012,7 +1012,34 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
+ this.trackEnteredOrExitedLavaOnVehicle();
+ this.updatePlayerAttributes();
+ this.advancements.flushDirty(this);
++
++ // KioCG start - ChunkHot
++ if (this.tickCount % 20 == 0){
++ this.nearbyChunkHot = this.refreshNearbyChunkHot();
++ }
++ // KioCG end
++ }
++
++ // KioCG start - ChunkHot
++ private volatile long nearbyChunkHot = 0;
++
++ public long getNearbyChunkHot() { return this.nearbyChunkHot; }
++
++ private long refreshNearbyChunkHot() {
++ long total = 0L;
++ int searchRadius = ((ServerLevel) this.level()).moonrise$getViewDistanceHolder().getViewDistances().tickViewDistance();
++ for (int i = this.moonrise$getSectionX() - searchRadius; i <= this.moonrise$getSectionX() + searchRadius; ++i) {
++ for (int j = this.moonrise$getSectionZ() - searchRadius; j <= this.moonrise$getSectionZ() + searchRadius; ++j) {
++ net.minecraft.world.level.chunk.LevelChunk targetChunk = this.level().getChunkIfLoaded(i, j);
++ if (targetChunk != null) {
++ total += targetChunk.getChunkHot().getAverage();
++ }
++ }
++ }
++ return total;
+ }
++ // KioCG end
++
+
+ private void updatePlayerAttributes() {
+ AttributeInstance attribute = this.getAttribute(Attributes.BLOCK_INTERACTION_RANGE);
+diff --git a/net/minecraft/world/entity/AreaEffectCloud.java b/net/minecraft/world/entity/AreaEffectCloud.java
+index 23b342cc31c7e72ade0e1ccad86a9ccf34380f13..249cb7326c8e4012dcffdb6bbb7bfc1f1eeb7b33 100644
+--- a/net/minecraft/world/entity/AreaEffectCloud.java
++++ b/net/minecraft/world/entity/AreaEffectCloud.java
+@@ -415,4 +415,11 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
+ public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
+ return false;
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return false;
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
+index 88ca22ed6af613370ca8691ad9ebeb113e1637fe..41313532c739027351d6fd848aa1c515aa4acd4a 100644
+--- a/net/minecraft/world/entity/Entity.java
++++ b/net/minecraft/world/entity/Entity.java
+@@ -5940,4 +5940,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ return ((ServerLevel) this.level).isPositionEntityTicking(this.blockPosition());
+ }
+ // Paper end - Expose entity id counter
++
++ public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
+ }
+diff --git a/net/minecraft/world/entity/LightningBolt.java b/net/minecraft/world/entity/LightningBolt.java
+index f003a65b34027dff14455860815c7d719c5289fa..6f9f8e52d2311343a0c0c3900a466c6a84f7de73 100644
+--- a/net/minecraft/world/entity/LightningBolt.java
++++ b/net/minecraft/world/entity/LightningBolt.java
+@@ -287,4 +287,11 @@ public class LightningBolt extends Entity {
+ public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
+ return false;
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return false;
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
+index 6394b0899095b047ca9266135fc44aa0c32467cf..af7dbb0f2df0ec42c2c16bc58ba16b6c65d3ebcb 100644
+--- a/net/minecraft/world/entity/Mob.java
++++ b/net/minecraft/world/entity/Mob.java
+@@ -1720,4 +1720,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
+ public float[] getArmorDropChances() {
+ return this.armorDropChances;
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return super.shouldTickHot() && (!this.removeWhenFarAway(0.0) || this.isPersistenceRequired() || this.requiresCustomPersistence());
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/entity/animal/horse/TraderLlama.java b/net/minecraft/world/entity/animal/horse/TraderLlama.java
+index c5b11a63bb2ab660efcc386ad9b4697e2a5efc97..f139822cb3e90b9d5fac6971e2ef1a8569d9849b 100644
+--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java
++++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java
+@@ -157,4 +157,11 @@ public class TraderLlama extends Llama {
+ super.start();
+ }
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return super.shouldTickHot() && !this.canDespawn();
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java
+index 6655d06e2011e20e7346dfe57527795269094d8a..48aa6fcb5c16fdbb4ae902cbb72c6b8e02820c88 100644
+--- a/net/minecraft/world/entity/npc/WanderingTrader.java
++++ b/net/minecraft/world/entity/npc/WanderingTrader.java
+@@ -320,4 +320,11 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
+ return !pos.closerToCenterThan(this.trader.position(), distance);
+ }
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return false;
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
+index eaa77200d6bc33faeefdc2d07b73ee7ddcd3afe8..5ff6973a033033ce1562762bb6f57268e1193900 100644
+--- a/net/minecraft/world/entity/player/Player.java
++++ b/net/minecraft/world/entity/player/Player.java
+@@ -1544,6 +1544,13 @@ public abstract class Player extends LivingEntity {
+ return true;
+ }
+
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return false;
++ }
++ // KioCG end
++
+ public Either startSleepInBed(BlockPos bedPos) {
+ // CraftBukkit start
+ return this.startSleepInBed(bedPos, false);
+diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
+index 20f8aed59ac953cac3029115f35e496f9784bec4..d54d96c354cd12e8300c7ddb65d92cd202d5ae48 100644
+--- a/net/minecraft/world/entity/projectile/Projectile.java
++++ b/net/minecraft/world/entity/projectile/Projectile.java
+@@ -513,4 +513,11 @@ public abstract class Projectile extends Entity implements TraceableEntity {
+ public interface ProjectileFactory {
+ T create(ServerLevel level, LivingEntity owner, ItemStack spawnedFrom);
+ }
++
++ // KioCG start
++ @Override
++ public boolean shouldTickHot() {
++ return false;
++ }
++ // KioCG end
+ }
+diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
+index 78211c68bf52c0cd402fee7bcdde223130d49b5c..83b0e91165024697f6b7d41d43142b2b33641968 100644
+--- a/net/minecraft/world/level/chunk/LevelChunk.java
++++ b/net/minecraft/world/level/chunk/LevelChunk.java
+@@ -103,6 +103,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
+ // Paper start - rewrite chunk system
+ private boolean postProcessingDone;
+ private net.minecraft.server.level.ServerChunkCache.ChunkAndHolder chunkAndHolder;
++ private final com.kiocg.ChunkHot chunkHot = new com.kiocg.ChunkHot(); public com.kiocg.ChunkHot getChunkHot() { return this.chunkHot; } // KioCG
+
+ @Override
+ public final boolean moonrise$isPostProcessingDone() {
+@@ -926,6 +927,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
+ try {
+ ProfilerFiller profilerFiller = Profiler.get();
+ profilerFiller.push(this::getType);
++ LevelChunk.this.chunkHot.startTicking(); // KioCG
+ profiler.startTimer(timerId); try { // Folia - profiler
+ BlockState blockState = LevelChunk.this.getBlockState(blockPos);
+ if (this.blockEntity.getType().isValid(blockState)) {
+@@ -940,7 +942,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
+ }
+ // Paper end - Remove the Block Entity if it's invalid
+ }
+- } finally { profiler.stopTimer(timerId); } // Folia - profiler
++ } finally { profiler.stopTimer(timerId); LevelChunk.this.chunkHot.stopTickingAndCount(); } // Folia - profiler // KioCG
+
+ profilerFiller.pop();
+ } catch (Throwable var5) {
+diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
+index 26c15c60d358273a3b369c286771c81d6f0979dd..715580a893ba9dd34ee562b81350b81f9da3f905 100644
+--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
+@@ -60,7 +60,10 @@ public interface NeighborUpdater {
+ }
+ }
+ // CraftBukkit end
++ net.minecraft.world.level.chunk.LevelChunk levelChunk = level.getChunkIfLoaded(pos); // KioCG
++ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
+ state.handleNeighborChanged(level, pos, neighborBlock, orientation, movedByPiston);
++ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
+ // Spigot start
+ } catch (StackOverflowError ex) {
+ level.lastPhysicsProblem = new BlockPos(pos);
diff --git a/luminol-server/minecraft-patches/features/0027-Purpur-use-alternative-keep-alive.patch b/luminol-server/minecraft-patches/features/0027-Purpur-use-alternative-keep-alive.patch
new file mode 100644
index 0000000..31e3895
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0027-Purpur-use-alternative-keep-alive.patch
@@ -0,0 +1,67 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:43:15 +0800
+Subject: [PATCH] Purpur use alternative keep alive
+
+
+diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+index 6eca15223b92aedac74233db886e2c1248750e2c..7507f32b5f0f7fbbf35eeaaf03bf9d99694c1683 100644
+--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+@@ -41,6 +41,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+ private long keepAliveChallenge;
+ private long closedListenerTime;
+ private boolean closed = false;
++ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur
+ private int latency;
+ private volatile boolean suspendFlushingOnServerThread = false;
+ // CraftBukkit start
+@@ -130,6 +131,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+
+ @Override
+ public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
++ // Purpur start
++ if (me.earthme.luminol.config.modules.optimizations.PurpurAlternativeKeepaliveConfig.useAlternateKeepAlive) {
++ if (this.keepAlivePending && !keepAlives.isEmpty() && keepAlives.contains(packet.getId())) {
++ int ping = (int) (Util.getMillis() - packet.getId());
++ this.latency = (this.latency * 3 + ping) / 4;
++ this.keepAlivePending = false;
++ keepAlives.clear(); // we got a valid response, lets roll with it and forget the rest
++ }
++ } else
++ // Purpur end
+ if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
+ int i = (int)(Util.getMillis() - this.keepAliveTime);
+ this.latency = (this.latency * 3 + i) / 4;
+@@ -250,7 +261,22 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+ // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings
+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2
+ final long elapsedTime = millis - this.keepAliveTime;
+- if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
++ // Purpur start
++ if (me.earthme.luminol.config.modules.optimizations.PurpurAlternativeKeepaliveConfig.useAlternateKeepAlive) {
++ if (elapsedTime >= 1000L) { // 1 second
++ if (this.keepAlivePending && !this.processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) {
++ LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName());
++ this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
++ } else if (this.checkIfClosed(millis)) {
++ this.keepAlivePending = true;
++ this.keepAliveTime = millis; // hijack this field for 1 second intervals
++ this.keepAlives.add(millis); // currentTime is ID
++ this.send(new ClientboundKeepAlivePacket(millis));
++ }
++ }
++ } else {
++
++ if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
+ if (this.keepAlivePending) {
+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
+ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
+@@ -263,6 +289,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+ this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
+ }
+ }
++ } // Purpur end
+
+ Profiler.get().pop();
+ }
diff --git a/luminol-server/minecraft-patches/features/0028-Petal-Reduce-sensor-work.patch b/luminol-server/minecraft-patches/features/0028-Petal-Reduce-sensor-work.patch
new file mode 100644
index 0000000..8def81d
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0028-Petal-Reduce-sensor-work.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:21:59 +0800
+Subject: [PATCH] Petal Reduce sensor work
+
+
+diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
+index af7dbb0f2df0ec42c2c16bc58ba16b6c65d3ebcb..53e78475e721a05e9757235d0849eae3878007cd 100644
+--- a/net/minecraft/world/entity/Mob.java
++++ b/net/minecraft/world/entity/Mob.java
+@@ -866,11 +866,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
+ return;
+ }
+ // Paper end - Allow nerfed mobs to jump and float
++ int i = this.tickCount + this.getId(); //Luminol - Petal - Move up
+ ProfilerFiller profilerFiller = Profiler.get();
+ profilerFiller.push("sensing");
+- this.sensing.tick();
++ if (i % me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.delayTicks == 0 || !me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.enabled) this.sensing.tick(); // Luminol - Petal - Reduce sensor work
+ profilerFiller.pop();
+- int i = this.tickCount + this.getId();
+ if (i % 2 != 0 && this.tickCount > 1) {
+ profilerFiller.push("targetSelector");
+ this.targetSelector.tickRunningGoals(false);
diff --git a/luminol-server/minecraft-patches/features/0029-Pufferfish-Cache-climbing-check-for-activation.patch b/luminol-server/minecraft-patches/features/0029-Pufferfish-Cache-climbing-check-for-activation.patch
new file mode 100644
index 0000000..b619e90
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0029-Pufferfish-Cache-climbing-check-for-activation.patch
@@ -0,0 +1,44 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:25:44 +0800
+Subject: [PATCH] Pufferfish Cache climbing check for activation
+
+
+diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
+index ba8b5a0ebe652bfaf5c1498c19d12a91a192bf8e..76e0b50b2dc9c718a67f89de720a891b398cec2a 100644
+--- a/io/papermc/paper/entity/activation/ActivationRange.java
++++ b/io/papermc/paper/entity/activation/ActivationRange.java
+@@ -225,7 +225,7 @@ public final class ActivationRange {
+ }
+ // special cases.
+ if (entity instanceof final LivingEntity living) {
+- if (living.onClimbable() || living.jumping || living.hurtTime > 0 || !living.activeEffects.isEmpty() || living.isFreezing()) {
++ if ( living.onClimableCached() || living.onClimbable() || living.jumping || living.hurtTime > 0 || !living.activeEffects.isEmpty() || living.isFreezing()) { // Pufferfish - use cached
+ return 1;
+ }
+ if (entity instanceof final Mob mob && mob.getTarget() != null) {
+diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
+index 5ba06cf6b26baa5acae9d64111ee3f61533e7867..d7eb8022a1606760d8e81bc752241eff4496ef4c 100644
+--- a/net/minecraft/world/entity/LivingEntity.java
++++ b/net/minecraft/world/entity/LivingEntity.java
+@@ -2039,6 +2039,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ return this.lastClimbablePos;
+ }
+
++
++ // Pufferfish start
++ private boolean cachedOnClimable = false;
++ private BlockPos lastClimbingPosition = null;
++
++ public boolean onClimableCached() {
++ if (!this.blockPosition().equals(this.lastClimbingPosition)) {
++ this.cachedOnClimable = this.onClimbable();
++ this.lastClimbingPosition = this.blockPosition();
++ }
++ return this.cachedOnClimable;
++ }
++ // Pufferfish end
++
+ public boolean onClimbable() {
+ if (this.isSpectator()) {
+ return false;
diff --git a/luminol-server/minecraft-patches/features/0030-Pufferfish-Reduce-chunk-loading-lookups.patch b/luminol-server/minecraft-patches/features/0030-Pufferfish-Reduce-chunk-loading-lookups.patch
new file mode 100644
index 0000000..b5d9ccf
--- /dev/null
+++ b/luminol-server/minecraft-patches/features/0030-Pufferfish-Reduce-chunk-loading-lookups.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:27:17 +0800
+Subject: [PATCH] Pufferfish Reduce chunk loading & lookups
+
+
+diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java
+index 4b5ffd278e0e9d47100e5452949e8d757bbfece4..772ccc4dc66253a84a6d24d00e271d9b4916f052 100644
+--- a/net/minecraft/world/entity/monster/EnderMan.java
++++ b/net/minecraft/world/entity/monster/EnderMan.java
+@@ -309,11 +309,18 @@ public class EnderMan extends Monster implements NeutralMob {
+ private boolean teleport(double x, double y, double z) {
+ BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, y, z);
+
+- while (mutableBlockPos.getY() > this.level().getMinY() && !this.level().getBlockState(mutableBlockPos).blocksMotion()) {
++ // Pufferfish start - single chunk lookup
++ net.minecraft.world.level.chunk.LevelChunk chunk = this.level().getChunkIfLoaded(mutableBlockPos);
++ if (chunk == null) {
++ return false;
++ }
++ // Pufferfish end
++ while (mutableBlockPos.getY() > this.level().getMinY() && !chunk.getBlockState(mutableBlockPos).blocksMotion()) { // Pufferfish
++
+ mutableBlockPos.move(Direction.DOWN);
+ }
+
+- BlockState blockState = this.level().getBlockState(mutableBlockPos);
++ BlockState blockState = chunk.getBlockState(mutableBlockPos); // Pufferfish
+ boolean flag = blockState.blocksMotion();
+ boolean isWater = blockState.getFluidState().is(FluidTags.WATER);
+ if (flag && !isWater) {
diff --git a/patches/server/0002-Rebrand-to-Luminol.patch b/luminol-server/paper-patches/features/0001-Rebrand-to-Luminol.patch
similarity index 98%
rename from patches/server/0002-Rebrand-to-Luminol.patch
rename to luminol-server/paper-patches/features/0001-Rebrand-to-Luminol.patch
index 319560c..479508f 100644
--- a/patches/server/0002-Rebrand-to-Luminol.patch
+++ b/luminol-server/paper-patches/features/0001-Rebrand-to-Luminol.patch
@@ -1,33 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Tue, 6 Feb 2024 01:35:36 +0000
+From: MrHua269
+Date: Sun, 12 Jan 2025 09:56:38 +0800
Subject: [PATCH] Rebrand to Luminol
-diff --git a/build.gradle.kts b/build.gradle.kts
-index dd6cc4972a209e58313a2b6c6fe87c3605fe34ae..17d2d18d7898e4f0898cc18c930b7cb26f826f2a 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -100,14 +100,14 @@ tasks.jar {
- val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper
- attributes(
- "Main-Class" to "org.bukkit.craftbukkit.Main",
-- "Implementation-Title" to "Folia", // Folia
-+ "Implementation-Title" to "Luminol", // Folia // Luminol
- "Implementation-Version" to implementationVersion,
- "Implementation-Vendor" to date, // Paper
-- "Specification-Title" to "Folia", // Folia
-+ "Specification-Title" to "Luminol", // Folia // Luminol
- "Specification-Version" to project.version,
-- "Specification-Vendor" to "Paper Team",
-- "Brand-Id" to "papermc:folia", // Folia
-- "Brand-Name" to "Folia", // Folia
-+ "Specification-Vendor" to "LuminolMC Team", // Luminol
-+ "Brand-Id" to "luminolmc:luminol", // Folia // Luminol
-+ "Brand-Name" to "Luminol", // Folia // Luminol
- "Build-Number" to (build ?: ""),
- "Build-Time" to Instant.now().toString(),
- "Git-Branch" to gitBranch, // Paper
diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java
index f5ff71e31516327be71924926938f1c9f0e503df..1ea251a202dc6386a110ee515d3329902f14e08e 100644
--- a/src/main/java/com/destroystokyo/paper/Metrics.java
diff --git a/patches/server/0003-Empty-config-file-base.patch b/luminol-server/paper-patches/features/0002-Added-luminol-config-framework.patch
similarity index 88%
rename from patches/server/0003-Empty-config-file-base.patch
rename to luminol-server/paper-patches/features/0002-Added-luminol-config-framework.patch
index 73a862f..a1cbc1c 100644
--- a/patches/server/0003-Empty-config-file-base.patch
+++ b/luminol-server/paper-patches/features/0002-Added-luminol-config-framework.patch
@@ -1,21 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 4 Dec 2024 23:07:13 +0800
-Subject: [PATCH] Empty config file base
+Date: Sun, 12 Jan 2025 10:15:53 +0800
+Subject: [PATCH] Added luminol config framework
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 17d2d18d7898e4f0898cc18c930b7cb26f826f2a..017dc1ff0a7c6f7c50a57bf615fc31947ed49639 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -26,6 +26,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
-
- dependencies {
- implementation(project(":luminol-api")) // Folia // Luminol
-+ implementation("com.electronwill.night-config:toml:3.6.6") // Luminol - Night config
- implementation("ca.spottedleaf:concurrentutil:0.0.2") // Paper - Add ConcurrentUtil dependency
- // Paper start
- implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
diff --git a/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c8745dffa80cf47e856d04d283937bda86881f8
@@ -581,28 +569,3 @@ index 0000000000000000000000000000000000000000..de94c8e39f0ae0da80d5a79af63413e2
+ // Paper end - lifecycle events
+}
\ No newline at end of file
-diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
-index 300a044bb0f0e377133f24469cea1a9669de6e58..b30690eba7f06e5af06fb3019e89c067629b77a6 100644
---- a/src/main/java/net/minecraft/server/Main.java
-+++ b/src/main/java/net/minecraft/server/Main.java
-@@ -123,6 +123,7 @@ public class Main {
- }
-
- io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper
-+ me.earthme.luminol.config.LuminolConfig.preLoadConfig(); //Luminol - load config file
- Bootstrap.bootStrap();
- Bootstrap.validate();
- Util.startTimerHackThread();
-diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index 78f33298e809a7f6d079d9f2c64e2caa47a1b25a..426efbc58deb56e044a6b51021ea63cd8f120a14 100644
---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -223,6 +223,8 @@ 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
- this.server.spark.enableEarlyIfRequested(); // Paper - spark
- // Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
- if (this.convertOldUsers()) {
diff --git a/patches/server/0004-Add-config-for-server-mod-name.patch b/luminol-server/paper-patches/features/0003-Add-config-for-server-mod-name.patch
similarity index 70%
rename from patches/server/0004-Add-config-for-server-mod-name.patch
rename to luminol-server/paper-patches/features/0003-Add-config-for-server-mod-name.patch
index a420090..88ef85a 100644
--- a/patches/server/0004-Add-config-for-server-mod-name.patch
+++ b/luminol-server/paper-patches/features/0003-Add-config-for-server-mod-name.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 7 Feb 2024 00:49:38 +0000
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:17:53 +0800
Subject: [PATCH] Add config for server mod name
@@ -46,16 +46,3 @@ index 0000000000000000000000000000000000000000..94e7c8910e3623163528a844fd7a08b3
+ return "server_mod_name";
+ }
+}
-diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 1676c4abb3f6f71bb7b25351aa58b4e127786fca..8cc0c01a19fc71753d7c3ed4fa7e9992aaf93b5a 100644
---- a/src/main/java/net/minecraft/server/MinecraftServer.java
-+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -2121,7 +2121,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
+Date: Sun, 12 Jan 2025 10:23:14 +0800
+Subject: [PATCH] Add config for unsafe teleportation
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..865ffe0051d84ac9018ab54a54894c2fe8fd573e
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
+@@ -0,0 +1,22 @@
++package me.earthme.luminol.config.modules.fixes;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class UnsafeTeleportationConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled", comments = "Allow non player entities enter end portals if enabled.\n" +
++ "If you want to use sand duping,please turn on this.\n" +
++ "Warning: This would cause some unsafe issues, you could learn more on : https://github.com/PaperMC/Folia/issues/297")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.FIXES;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "allow_unsafe_teleportation";
++ }
++}
diff --git a/patches/server/0006-Add-config-for-vanilla-random.patch b/luminol-server/paper-patches/features/0005-Add-config-for-vanilla-random.patch
similarity index 51%
rename from patches/server/0006-Add-config-for-vanilla-random.patch
rename to luminol-server/paper-patches/features/0005-Add-config-for-vanilla-random.patch
index 7f7139b..837e84e 100644
--- a/patches/server/0006-Add-config-for-vanilla-random.patch
+++ b/luminol-server/paper-patches/features/0005-Add-config-for-vanilla-random.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 31 Jul 2024 12:02:01 +0800
+Date: Sun, 12 Jan 2025 10:24:51 +0800
Subject: [PATCH] Add config for vanilla random
@@ -30,16 +30,3 @@ index 0000000000000000000000000000000000000000..0e6bfc03be660415c333024b56ac6565
+ return "use_vanilla_random_source";
+ }
+}
-diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 20fe53cc8e9edfc7b7d50f23379e0044e520c84d..eeb094265756e5440c0cdd0784f725f7de536493 100644
---- a/src/main/java/net/minecraft/world/entity/Entity.java
-+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -590,7 +590,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
- this.bb = Entity.INITIAL_AABB;
- this.stuckSpeedMultiplier = Vec3.ZERO;
- this.nextStep = 1.0F;
-- this.random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
-+ this.random = me.earthme.luminol.config.modules.fixes.VanillaRandomSourceConfig.useLegacyRandomSourceForPlayers ? RandomSource.create() : SHARED_RANDOM;//Luminol - Add config for vanilla random SHARED_RANDOM // Paper - Share random for entities to make them more random
- this.remainingFireTicks = -this.getFireImmuneTicks();
- this.fluidHeight = new Object2DoubleArrayMap(2);
- this.fluidOnEyes = new HashSet();
diff --git a/patches/server/0008-Add-a-simple-tpsbar.patch b/luminol-server/paper-patches/features/0006-Add-a-simple-tpsbar.patch
similarity index 85%
rename from patches/server/0008-Add-a-simple-tpsbar.patch
rename to luminol-server/paper-patches/features/0006-Add-a-simple-tpsbar.patch
index 3cef546..ed90288 100644
--- a/patches/server/0008-Add-a-simple-tpsbar.patch
+++ b/luminol-server/paper-patches/features/0006-Add-a-simple-tpsbar.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 31 Jul 2024 12:05:39 +0800
+Date: Sun, 12 Jan 2025 10:27:31 +0800
Subject: [PATCH] Add a simple tpsbar
@@ -335,36 +335,11 @@ index 0000000000000000000000000000000000000000..de2f03d6e771c09e8da2da454b7ec4a1
+ return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(2));
+ }
+}
-diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index e3c8deea68ef49bcd07359e243a12afb57cbcf52..279bc6eede3a1ae77b810f0553efe36adeeefaa4 100644
---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -802,6 +802,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
-
- @Override
- public void stopServer() {
-+ me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar
- super.stopServer();
- //Util.shutdownExecutors(); // Paper - moved into super
- SkullBlockEntity.clear();
-diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 23f852ede94bce4d000c8fcaa8fba5d4800b533c..0752d13febc5f1831ae58f7216fba89e1290c780 100644
---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
-+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -327,7 +327,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
- public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
- public @Nullable String clientBrandName = null; // Paper - Brand support
- public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
--
-+ public volatile boolean isTpsBarVisible = false; //Luminol - Tps bar
- // Paper start - rewrite chunk system
- private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
- private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-index b0e93050839ce00b057e3a9bf3bdf8dd5e0662cf..c39e9ea1ce46864623a6d15027ce337611e6b712 100644
+index 5aa9fcb697a758da10a9e1f839dd5502a446c076..3a243a0c33fe402d0337541a7ca7d0f6c53efe76 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-@@ -2414,6 +2414,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -2396,6 +2396,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
handle.expToDrop = data.getInt("expToDrop");
handle.keepLevel = data.getBoolean("keepLevel");
}
@@ -374,7 +349,7 @@ index b0e93050839ce00b057e3a9bf3bdf8dd5e0662cf..c39e9ea1ce46864623a6d15027ce3376
}
}
-@@ -2435,6 +2438,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -2417,6 +2420,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
data.putLong("lastPlayed", System.currentTimeMillis());
data.putString("lastKnownName", handle.getScoreboardName());
diff --git a/patches/server/0009-Add-a-simple-membar.patch b/luminol-server/paper-patches/features/0007-Add-a-simple-membar.patch
similarity index 83%
rename from patches/server/0009-Add-a-simple-membar.patch
rename to luminol-server/paper-patches/features/0007-Add-a-simple-membar.patch
index 3699aed..0e96346 100644
--- a/patches/server/0009-Add-a-simple-membar.patch
+++ b/luminol-server/paper-patches/features/0007-Add-a-simple-membar.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 31 Jul 2024 12:18:09 +0800
+Date: Sun, 12 Jan 2025 10:28:04 +0800
Subject: [PATCH] Add a simple membar
@@ -290,35 +290,11 @@ index 0000000000000000000000000000000000000000..3535cf03e7855b4d8b312ccf3a7b0564
+ return BossBar.Color.valueOf(MembarConfig.memColors.get(2));
+ }
+}
-diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index 279bc6eede3a1ae77b810f0553efe36adeeefaa4..4ff5105d32c41a8ea145e7833ea6a3cee0108031 100644
---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -803,6 +803,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
- @Override
- public void stopServer() {
- me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar
-+ me.earthme.luminol.functions.GlobalServerMemoryBar.cancelBarUpdateTask(); //Luminol - Memory bar
- super.stopServer();
- //Util.shutdownExecutors(); // Paper - moved into super
- SkullBlockEntity.clear();
-diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 0752d13febc5f1831ae58f7216fba89e1290c780..93c038ba1fd216fd11ab8b5cec5807453f34e152 100644
---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
-+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -328,6 +328,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
- public @Nullable String clientBrandName = null; // Paper - Brand support
- public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
- public volatile boolean isTpsBarVisible = false; //Luminol - Tps bar
-+ public volatile boolean isMemBarVisible = false; //Luminol - Memory bar
- // Paper start - rewrite chunk system
- private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader;
- private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-index c39e9ea1ce46864623a6d15027ce337611e6b712..1872b19dfefb40e6673fd2b8ddb8d3c384020073 100644
+index 3a243a0c33fe402d0337541a7ca7d0f6c53efe76..39ac96a61e48750a420ea612e37e3f8195569f10 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-@@ -2417,6 +2417,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -2399,6 +2399,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
//Luminol start - Tpsbar
getHandle().isTpsBarVisible = data.getBoolean("tpsbarVisible");
//Luminol end
@@ -328,7 +304,7 @@ index c39e9ea1ce46864623a6d15027ce337611e6b712..1872b19dfefb40e6673fd2b8ddb8d3c3
}
}
-@@ -2441,6 +2444,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -2423,6 +2426,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
//Luminol start - Tpsbar
data.putBoolean("tpsbarVisible",handle.isTpsBarVisible);
//Luminol end
diff --git a/luminol-server/paper-patches/features/0008-Add-config-for-offline-mode-warning.patch b/luminol-server/paper-patches/features/0008-Add-config-for-offline-mode-warning.patch
new file mode 100644
index 0000000..43c70fd
--- /dev/null
+++ b/luminol-server/paper-patches/features/0008-Add-config-for-offline-mode-warning.patch
@@ -0,0 +1,58 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:29:45 +0800
+Subject: [PATCH] Add config for offline mode warning
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..502b93c7bda9e8577a1901a8777b7cf9b9bdc36b
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.misc;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class OfflineModeWarningConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = true;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.MISC;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "warn_on_offline_mode";
++ }
++}
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..c7e4724cc4ab8d911bcaf0106c098b266c843bb1
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.misc;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class UsernameCheckConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = true;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.MISC;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "username_checks";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch b/luminol-server/paper-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch
new file mode 100644
index 0000000..04a0dbb
--- /dev/null
+++ b/luminol-server/paper-patches/features/0009-Add-config-for-out-of-order-chat-checks.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:30:03 +0800
+Subject: [PATCH] Add config for out-of-order chat checks
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..83176a8a7e993b51a0663b0f76161884abbf4951
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.misc;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class InorderChatConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = true;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.MISC;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "mojang_out_of_order_chat_check";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch b/luminol-server/paper-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch
new file mode 100644
index 0000000..e8691fc
--- /dev/null
+++ b/luminol-server/paper-patches/features/0010-Add-config-to-verify-signature-only-in-online-mode.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:31:09 +0800
+Subject: [PATCH] Add config to verify signature only in online-mode
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..e45ce3abf49684c911678abcefd69586246cc0e3
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java
+@@ -0,0 +1,21 @@
++package me.earthme.luminol.config.modules.misc;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class PublickeyVerifyConfig implements IConfigModule {
++
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.MISC;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "verify_publickey_only_in_online_mode";
++ }
++}
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..8def8aad908f5e6b828d7d9179bfe1962c39f9f7
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.misc;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class TripwireConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.MISC;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "tripwire_dupe";
++ }
++}
diff --git a/patches/server/0015-Add-config-to-disable-entity-tick-catchers.patch b/luminol-server/paper-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch
similarity index 51%
rename from patches/server/0015-Add-config-to-disable-entity-tick-catchers.patch
rename to luminol-server/paper-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch
index 65db21d..5da9e9b 100644
--- a/patches/server/0015-Add-config-to-disable-entity-tick-catchers.patch
+++ b/luminol-server/paper-patches/features/0011-Add-config-to-disable-entity-tick-catchers.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 7 Aug 2024 14:27:24 +0800
+Date: Sun, 12 Jan 2025 10:35:13 +0800
Subject: [PATCH] Add config to disable entity tick catchers
@@ -30,16 +30,3 @@ index 0000000000000000000000000000000000000000..0fd71151a85dd87c2294033e2e7512ac
+ return "disable_entity_exception_catchers";
+ }
+}
-diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 456f15e44e41d65338c0346594be2b0042b84005..5127d0ef0c85b8f57d412d36eaca00153c4fe7b3 100644
---- a/src/main/java/net/minecraft/world/level/Level.java
-+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -1538,7 +1538,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
- try {
- tickConsumer.accept(entity);
- } catch (Throwable throwable) {
-- if (throwable instanceof ThreadDeath) throw throwable; // Paper
-+ if (throwable instanceof ThreadDeath || me.earthme.luminol.config.modules.experiment.DisableEntityCatchConfig.enabled) throw throwable; // Paper // Luminol
- // Paper start - Prevent block entity and entity crashes
- final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
- MinecraftServer.LOGGER.error(msg, throwable);
diff --git a/patches/server/0016-Add-config-to-disable-async-catchers.patch b/luminol-server/paper-patches/features/0012-Add-config-to-disable-async-catchers.patch
similarity index 61%
rename from patches/server/0016-Add-config-to-disable-async-catchers.patch
rename to luminol-server/paper-patches/features/0012-Add-config-to-disable-async-catchers.patch
index 2394015..04932b7 100644
--- a/patches/server/0016-Add-config-to-disable-async-catchers.patch
+++ b/luminol-server/paper-patches/features/0012-Add-config-to-disable-async-catchers.patch
@@ -1,14 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 7 Aug 2024 14:34:15 +0800
+Date: Sun, 12 Jan 2025 10:35:49 +0800
Subject: [PATCH] Add config to disable async catchers
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
-index 301cc1c0d91f5e755f74ace60dbe5551240b496d..2befb04b18cbdcc854437dfc534832ae02e70ee6 100644
+index 5aa2891d52fb246329bf3483059b069b86fd621a..0724ec897a4ac70469f2c9cd740ea41cb71971a1 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
-@@ -26,49 +26,49 @@ public class TickThread extends Thread {
+@@ -26,14 +26,14 @@ public class TickThread extends Thread {
*/
@Deprecated
public static void ensureTickThread(final String reason) {
@@ -22,49 +22,54 @@ index 301cc1c0d91f5e755f74ace60dbe5551240b496d..2befb04b18cbdcc854437dfc534832ae
public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) {
- if (!isTickThreadFor(world, pos)) {
+ if (!isTickThreadFor(world, pos) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos;
+ LOGGER.error(ex, new Throwable());
+@@ -51,7 +51,7 @@ public class TickThread extends Thread {
}
public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) {
- if (!isTickThreadFor(world, pos)) {
+ if (!isTickThreadFor(world, pos) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos;
+ LOGGER.error(ex, new Throwable());
+@@ -60,7 +60,7 @@ public class TickThread extends Thread {
}
public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) {
- if (!isTickThreadFor(world, chunkX, chunkZ)) {
+ if (!isTickThreadFor(world, chunkX, chunkZ) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ);
+ LOGGER.error(ex, new Throwable());
+@@ -69,7 +69,7 @@ public class TickThread extends Thread {
}
public static void ensureTickThread(final Entity entity, final String reason) {
- if (!isTickThreadFor(entity)) {
+ if (!isTickThreadFor(entity) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", entity=" + entity;
+ LOGGER.error(ex, new Throwable());
+@@ -78,7 +78,7 @@ public class TickThread extends Thread {
}
public static void ensureTickThread(final Level world, final AABB aabb, final String reason) {
- if (!isTickThreadFor(world, aabb)) {
+ if (!isTickThreadFor(world, aabb) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb;
+ LOGGER.error(ex, new Throwable());
+@@ -87,7 +87,7 @@ public class TickThread extends Thread {
}
public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) {
- if (!isTickThreadFor(world, blockX, blockZ)) {
+ if (!isTickThreadFor(world, blockX, blockZ) && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Luminol
- LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
- throw new IllegalStateException(reason);
- }
+ final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
+ reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ);
+ LOGGER.error(ex, new Throwable());
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/DisableAsyncCatcherConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/DisableAsyncCatcherConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..61f653eeca366672ded88c491cf5c59e546e7301
@@ -92,15 +97,15 @@ index 0000000000000000000000000000000000000000..61f653eeca366672ded88c491cf5c59e
+ }
+}
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
-index 1f23e775eba1c34e01145bd91b0ce26fed6ca9de..3e0dbf379fc1b5baa27936cb902b3c54f9b0f4c9 100644
+index 50f01faa88c8c658252fade3748f20e48e9c8432..36fa1f83c3286e10cc7c208a2a2f1a718d525ad8 100644
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
-@@ -9,7 +9,7 @@ public class AsyncCatcher
+@@ -7,7 +7,7 @@ public class AsyncCatcher {
+ public static boolean enabled = true;
- public static void catchOp(String reason)
- {
-- if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) // Paper // Paper - rewrite chunk system
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread() && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) // Paper // Paper - rewrite chunk system // Luminol
- {
- MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); // Paper
- throw new IllegalStateException( "Asynchronous " + reason + "!" );
+ public static void catchOp(String reason) {
+- if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { // Paper - chunk system
++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread() && !me.earthme.luminol.config.modules.experiment.DisableAsyncCatcherConfig.enabled) { // Paper - chunk system // Luminol
+ MinecraftServer.LOGGER.error("Thread {} failed main thread check: {}", Thread.currentThread().getName(), reason, new Throwable()); // Paper
+ throw new IllegalStateException("Asynchronous " + reason + "!");
+ }
diff --git a/patches/server/0017-Add-experiment-config-for-command-block-command-exec.patch b/luminol-server/paper-patches/features/0013-Add-experiment-config-for-command-block-command-exec.patch
similarity index 54%
rename from patches/server/0017-Add-experiment-config-for-command-block-command-exec.patch
rename to luminol-server/paper-patches/features/0013-Add-experiment-config-for-command-block-command-exec.patch
index 726b3a4..3a4ee0e 100644
--- a/patches/server/0017-Add-experiment-config-for-command-block-command-exec.patch
+++ b/luminol-server/paper-patches/features/0013-Add-experiment-config-for-command-block-command-exec.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 31 Aug 2024 10:56:58 +0800
+Date: Sun, 12 Jan 2025 10:36:32 +0800
Subject: [PATCH] Add experiment config for command block command execution
@@ -30,16 +30,3 @@ index 0000000000000000000000000000000000000000..3eafc59cc015569d3da8b1d8c4bfd046
+ return "force_enable_command_block_execution";
+ }
+}
-diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
-index ccf476d1ed22cf992e3cbca6a375d36f85a82fa8..81f69938ccc72522090c4bee1a941c0de8054feb 100644
---- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
-+++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java
-@@ -117,7 +117,7 @@ public abstract class BaseCommandBlock implements CommandSource {
- }
-
- public boolean performCommand(Level world) {
-- if (true) return false; // Folia - region threading
-+ if (!me.earthme.luminol.config.modules.experiment.CommandBlockConfig.enabled) return false; // Folia - region threading // Luminol
- if (!world.isClientSide && world.getGameTime() != this.lastExecution) {
- if ("Searge".equalsIgnoreCase(this.command)) {
- this.lastOutput = Component.literal("#itzlipofutzli");
diff --git a/patches/server/0019-Add-configurable-region-format-framework-linear-v2-r.patch b/luminol-server/paper-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch
similarity index 56%
rename from patches/server/0019-Add-configurable-region-format-framework-linear-v2-r.patch
rename to luminol-server/paper-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch
index 38644f8..6f2d53b 100644
--- a/patches/server/0019-Add-configurable-region-format-framework-linear-v2-r.patch
+++ b/luminol-server/paper-patches/features/0014-Add-configurable-region-format-framework-linear-v2-r.patch
@@ -1,29 +1,13 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sun, 15 Dec 2024 12:53:33 +0800
+Date: Sun, 12 Jan 2025 10:49:22 +0800
Subject: [PATCH] Add configurable region format framework & linear v2 region
format support
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 017dc1ff0a7c6f7c50a57bf615fc31947ed49639..8f23bf19618382ccf5fd10a0b17b57cd445dea58 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -82,6 +82,11 @@ dependencies {
- implementation("me.lucko:spark-api:0.1-20240720.200737-2")
- implementation("me.lucko:spark-paper:1.10.119-SNAPSHOT")
- // Paper end - spark
-+ // Abomination start
-+ implementation("com.github.luben:zstd-jni:1.5.4-1")
-+ implementation("org.lz4:lz4-java:1.8.0")
-+ implementation("net.openhft:zero-allocation-hashing:0.16")
-+ // Abomination end
- }
-
- paperweight {
diff --git a/src/main/java/abomination/IRegionFile.java b/src/main/java/abomination/IRegionFile.java
new file mode 100644
-index 0000000000000000000000000000000000000000..d92f1d549c7e01daa6b5bba7d405e462a9d57e27
+index 0000000000000000000000000000000000000000..fda43a34c89d75e3036f14da3c6efcf157189b22
--- /dev/null
+++ b/src/main/java/abomination/IRegionFile.java
@@ -0,0 +1,39 @@
@@ -39,7 +23,7 @@ index 0000000000000000000000000000000000000000..d92f1d549c7e01daa6b5bba7d405e462
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+
-+public interface IRegionFile extends ChunkSystemRegionFile {
++public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable {
+ Path getPath();
+
+ DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
@@ -694,46 +678,6 @@ index 0000000000000000000000000000000000000000..bb0fcf5f47b5ae3d86e1d0572f951236
+ }
+ }
+}
-diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
-index a814512fcfb85312474ae2c2c21443843bf57831..2e084a5b28cbe4737f48c25e10af589213525362 100644
---- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
-+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
-@@ -8,9 +8,9 @@ public interface ChunkSystemRegionFileStorage {
-
- public boolean moonrise$doesRegionFileNotExistNoIO(final int chunkX, final int chunkZ);
-
-- public RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ);
-+ public abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // Luminol - Configurable region file format
-
-- public RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException;
-+ public abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // Luminol - Configurable region file format
-
- public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(
- final int chunkX, final int chunkZ, final CompoundTag compound
-diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
-index 1acea58838f057ab87efd103cbecb6f5aeaef393..f9b89684208b9fe2c93f0368f7df5a400061f6c7 100644
---- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
-+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
-@@ -1462,7 +1462,7 @@ public final class MoonriseRegionFileIO {
-
- public static interface IORunnable {
-
-- public void run(final RegionFile regionFile) throws IOException;
-+ public void run(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
-
- }
- }
-diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
-index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d5815c8c1 100644
---- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
-+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
-@@ -8,5 +8,5 @@ public interface ChunkSystemChunkBuffer {
-
- public void moonrise$setWriteOnClose(final boolean value);
-
-- public void moonrise$write(final RegionFile regionFile) throws IOException;
-+ public void moonrise$write(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
- }
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb689b6b79143ffaf1eadcba84feca0c632d1407
@@ -873,324 +817,3 @@ index 0000000000000000000000000000000000000000..5af068489646ed70330d8c6242ec88f5
+import java.nio.file.Path;
+
+public record RegionCreatorInfo (RegionStorageInfo info, Path filePath, Path folder, boolean sync) {}
-diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 8cc0c01a19fc71753d7c3ed4fa7e9992aaf93b5a..04f68856cb3d982f1644d26f5ae57587b6e36ff2 100644
---- a/src/main/java/net/minecraft/server/MinecraftServer.java
-+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -1036,10 +1036,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap());
- volatile Component status = Component.translatable("optimizeWorld.stage.counting");
-- static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
-+ static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\\\"+ net.minecraft.world.level.chunk.storage.RegionFileStorage.getExtensionName() +"$"); // Luminol - Configurable region file format
- final DimensionDataStorage overworldDataStorage;
-
- public WorldUpgrader(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, RegistryAccess dynamicRegistryManager, boolean eraseCache, boolean recreateRegionFiles) {
-@@ -399,7 +399,7 @@ public class WorldUpgrader implements AutoCloseable {
-
- private static List getAllChunkPositions(RegionStorageInfo key, Path regionDirectory) {
- File[] afile = regionDirectory.toFile().listFiles((file, s) -> {
-- return s.endsWith(".mca");
-+ return s.endsWith(net.minecraft.world.level.chunk.storage.RegionFileStorage.getExtensionName()); // Luminol - Configurable region file format
- });
-
- if (afile == null) {
-@@ -419,7 +419,7 @@ public class WorldUpgrader implements AutoCloseable {
- List list1 = Lists.newArrayList();
-
- try {
-- RegionFile regionfile = new RegionFile(key, file.toPath(), regionDirectory, true);
-+ abomination.IRegionFile regionfile = net.minecraft.world.level.chunk.storage.RegionFileStorage.createNew(key, file.toPath(), regionDirectory, true); // Luminol - Configurable region file format
-
- try {
- for (int i1 = 0; i1 < 32; ++i1) {
-@@ -482,7 +482,7 @@ public class WorldUpgrader implements AutoCloseable {
-
- protected abstract boolean tryProcessOnePosition(T storage, ChunkPos chunkPos, ResourceKey worldKey);
-
-- private void onFileFinished(RegionFile regionFile) {
-+ private void onFileFinished(abomination.IRegionFile regionFile) { // Luminol - Configurable region file format
- if (WorldUpgrader.this.recreateRegionFiles) {
- if (this.previousWriteFuture != null) {
- this.previousWriteFuture.join();
-@@ -507,7 +507,7 @@ public class WorldUpgrader implements AutoCloseable {
- }
- }
-
-- static record FileToUpgrade(RegionFile file, List chunksToUpgrade) {
-+ static record FileToUpgrade(abomination.IRegionFile file, List chunksToUpgrade) { // Luminol - Configurable region file format
-
- }
-
-diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
-index 16f07007a0f73ec0c6f421c9b082518e87e8cc7b..fc69834e18e0860750d878e1361722fc38b513f8 100644
---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
-+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
-@@ -28,7 +28,7 @@ import net.minecraft.nbt.NbtIo; // Paper
- import net.minecraft.world.level.ChunkPos;
- import org.slf4j.Logger;
-
--public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
-+public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile , abomination.IRegionFile{ // Paper - rewrite chunk system // Luminol - Configurable region file format
-
- private static final Logger LOGGER = LogUtils.getLogger();
- private static final int SECTOR_BYTES = 4096;
-@@ -129,7 +129,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
- }
-
- // note: only call for CHUNK regionfiles
-- boolean recalculateHeader() throws IOException {
-+ public boolean recalculateHeader() throws IOException { // Luminol - Configurable region file format // Luminol - Configurable region file format
- if (!this.canRecalcHeader) {
- return false;
- }
-@@ -810,7 +810,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
- }
- }
-
-- protected synchronized void write(ChunkPos pos, ByteBuffer buf) throws IOException {
-+ public synchronized void write(ChunkPos pos, ByteBuffer buf) throws IOException { // Luminol - Configurable region file format
- int i = RegionFile.getOffsetIndex(pos);
- int j = this.offsets.get(i);
- int k = RegionFile.getSectorNumber(j);
-@@ -952,10 +952,10 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
- private static int getChunkIndex(int x, int z) {
- return (x & 31) + (z & 31) * 32;
- }
-- synchronized boolean isOversized(int x, int z) {
-+ public synchronized boolean isOversized(int x, int z) { // Luminol - Configurable region file format
- return this.oversized[getChunkIndex(x, z)] == 1;
- }
-- synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
-+ public synchronized void setOversized(int x, int z, boolean oversized) throws IOException { // Luminol - Configurable region file format
- final int offset = getChunkIndex(x, z);
- boolean previous = this.oversized[offset] == 1;
- this.oversized[offset] = (byte) (oversized ? 1 : 0);
-@@ -994,7 +994,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
- return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
- }
-
-- synchronized CompoundTag getOversizedData(int x, int z) throws IOException {
-+ public synchronized CompoundTag getOversizedData(int x, int z) throws IOException { // Luminol - Configurable region file format
- Path file = getOversizedFile(x, z);
- try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new InflaterInputStream(Files.newInputStream(file))))) {
- return NbtIo.read((java.io.DataInput) out);
-@@ -1021,7 +1021,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
- }
-
- @Override
-- public final void moonrise$write(final RegionFile regionFile) throws IOException {
-+ public final void moonrise$write(final abomination.IRegionFile regionFile) throws IOException { // Luminol - Configurable region file format
- regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count));
- }
- // Paper end - rewrite chunk system
-diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
-index e40665cead218502b44dd49051a53326ed94f061..a25e1bfd74b7ec9d6fcc3fe7c4369bc20b33a0da 100644
---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
-+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
-@@ -23,7 +23,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
-
- public static final String ANVIL_EXTENSION = ".mca";
- private static final int MAX_CACHE_SIZE = 256;
-- public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap();
-+ public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); // Luminol - Configurable region file format
- private final RegionStorageInfo info;
- private final Path folder;
- private final boolean sync;
-@@ -33,8 +33,27 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- private static final int MAX_NON_EXISTING_CACHE = 1024 * 4;
- private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
- private static String getRegionFileName(final int chunkX, final int chunkZ) {
-- return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".mca";
-+ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + getExtensionName(); // Luminol - Configurable region file format
- }
-+ // Luminol start - Configurable region file format
-+ public static abomination.IRegionFile createNew(RegionStorageInfo info, Path filePath, Path folder, boolean sync) throws IOException{
-+ final me.earthme.luminol.utils.EnumRegionFormat regionFormat = me.earthme.luminol.config.modules.misc.RegionFormatConfig.regionFormat;
-+ final String fullFileName = filePath.getFileName().toString();
-+ final String[] fullNameSplit = fullFileName.split("\\.");
-+ final String extensionName = fullNameSplit[fullNameSplit.length - 1];
-+
-+ if (!regionFormat.getArgument().equalsIgnoreCase(extensionName)) {
-+ net.minecraft.server.MinecraftServer.setFatalException(new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument()));
-+ throw new IOException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
-+ }
-+
-+ return regionFormat.getCreator().create(new me.earthme.luminol.utils.RegionCreatorInfo(info, filePath, folder, sync));
-+ }
-+
-+ public static String getExtensionName() {
-+ return "." + me.earthme.luminol.config.modules.misc.RegionFormatConfig.regionFormat.getArgument();
-+ }
-+ // Luminol end
-
- private boolean doesRegionFilePossiblyExist(final long position) {
- synchronized (this.nonExistingRegionFiles) {
-@@ -68,15 +87,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- }
-
- @Override
-- public synchronized final RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) {
-+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // Luminol - Configurable region file format
- return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT));
- }
-
- @Override
-- public synchronized final RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException {
-+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // Luminol - Configurable region file format
- final long key = ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
-
-- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
-+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
- if (ret != null) {
- return ret;
- }
-@@ -100,7 +119,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
-
- FileUtil.createDirectoriesSafe(this.folder);
-
-- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
-+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
-
- this.regionCache.putAndMoveToFirst(key, ret);
-
-@@ -119,7 +138,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- }
-
- final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
-- final RegionFile regionFile = this.getRegionFile(pos);
-+ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
-
- // note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
- // (and, the regionfile parameter is unused for writing until the write call)
-@@ -153,7 +172,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- ) throws IOException {
- final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
- if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
-- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
-+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
- if (regionFile != null) {
- regionFile.clear(pos);
- } // else: didn't exist
-@@ -168,7 +187,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.ReadData moonrise$readData(
- final int chunkX, final int chunkZ
- ) throws IOException {
-- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
-+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
-
- final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
-
-@@ -221,7 +240,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- @Nullable
- public static ChunkPos getRegionFileCoordinates(Path file) {
- String fileName = file.getFileName().toString();
-- if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) {
-+ if (!fileName.startsWith("r.") || !fileName.endsWith(getExtensionName())) { // Luminol - Configurable region file format
- return null;
- }
-
-@@ -250,12 +269,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- }
-
- // Paper start - rewrite chunk system
-- public RegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException {
-+ public abomination.IRegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException { // Luminol - Configurable region file format
- return this.getRegionFile(chunkcoordintpair, false);
- }
- // Paper end - rewrite chunk system
-
-- public RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - public
-+ public abomination.IRegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - public // Luminol - Configurable region file format
- // Paper start - rewrite chunk system
- if (existingOnly) {
- return this.moonrise$getRegionFileIfExists(chunkcoordintpair.x, chunkcoordintpair.z);
-@@ -263,7 +282,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- synchronized (this) {
- final long key = ChunkPos.asLong(chunkcoordintpair.x >> REGION_SHIFT, chunkcoordintpair.z >> REGION_SHIFT);
-
-- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
-+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
- if (ret != null) {
- return ret;
- }
-@@ -278,7 +297,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
-
- FileUtil.createDirectoriesSafe(this.folder);
-
-- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
-+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
-
- this.regionCache.putAndMoveToFirst(key, ret);
-
-@@ -292,7 +311,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
- }
-
-- private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
-+ private static CompoundTag readOversizedChunk(abomination.IRegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // Luminol - Configurable region file format
- synchronized (regionfile) {
- try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
- CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
-@@ -327,7 +346,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- @Nullable
- public CompoundTag read(ChunkPos pos) throws IOException {
- // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
-- RegionFile regionfile = this.getRegionFile(pos, true);
-+ abomination.IRegionFile regionfile = this.getRegionFile(pos, true); // Luminol - Configurable region file format
- if (regionfile == null) {
- return null;
- }
-@@ -391,7 +410,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
-
- public void scanChunk(ChunkPos chunkPos, StreamTagVisitor scanner) throws IOException {
- // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
-- RegionFile regionfile = this.getRegionFile(chunkPos, true);
-+ abomination.IRegionFile regionfile = this.getRegionFile(chunkPos, true); // Luminol - Configurable region file format
- if (regionfile == null) {
- return;
- }
-@@ -421,7 +440,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- }
-
- public void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { // Paper - rewrite chunk system - public
-- RegionFile regionfile = this.getRegionFile(pos, nbt == null); // CraftBukkit // Paper - rewrite chunk system
-+ abomination.IRegionFile regionfile = this.getRegionFile(pos, nbt == null); // CraftBukkit // Paper - rewrite chunk system // Luminol - Configurable region file format
- // Paper start - rewrite chunk system
- if (regionfile == null) {
- // if the RegionFile doesn't exist, no point in deleting from it
-@@ -465,7 +484,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- // Paper start - rewrite chunk system
- synchronized (this) {
- final ExceptionCollector exceptionCollector = new ExceptionCollector<>();
-- for (final RegionFile regionFile : this.regionCache.values()) {
-+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
- try {
- regionFile.close();
- } catch (final IOException ex) {
-@@ -482,7 +501,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- // Paper start - rewrite chunk system
- synchronized (this) {
- final ExceptionCollector exceptionCollector = new ExceptionCollector<>();
-- for (final RegionFile regionFile : this.regionCache.values()) {
-+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
- try {
- regionFile.flush();
- } catch (final IOException ex) {
diff --git a/patches/server/0020-Add-config-for-watchdog-timeout.patch b/luminol-server/paper-patches/features/0015-Add-config-for-watchdog-timeout.patch
similarity index 53%
rename from patches/server/0020-Add-config-for-watchdog-timeout.patch
rename to luminol-server/paper-patches/features/0015-Add-config-for-watchdog-timeout.patch
index e2357b5..552495b 100644
--- a/patches/server/0020-Add-config-for-watchdog-timeout.patch
+++ b/luminol-server/paper-patches/features/0015-Add-config-for-watchdog-timeout.patch
@@ -1,22 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Tue, 31 Dec 2024 17:45:55 +0800
+Date: Sun, 12 Jan 2025 10:51:22 +0800
Subject: [PATCH] Add config for watchdog timeout
-diff --git a/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java b/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
-index 258d82ab2c78482e1561343e8e1f81fc33f1895e..967107c0f4a18a29877883ccddb4d7962f4b5788 100644
---- a/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
-+++ b/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
-@@ -65,7 +65,7 @@ public final class FoliaWatchdogThread extends Thread {
-
- for (final RunningTick tick : ticks) {
- final long elapsed = now - tick.lastPrint;
-- if (elapsed <= TimeUnit.SECONDS.toNanos(5L)) {
-+ if (elapsed <= TimeUnit.MILLISECONDS.toNanos(me.earthme.luminol.config.modules.misc.FoliaWatchogConfig.tickRegionTimeOutMs)) { // Luminol - Add config for watchdog timeout
- continue;
- }
- tick.lastPrint = now;
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/FoliaWatchogConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/FoliaWatchogConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..de58b5bf9dedf35bc56a9211d0769b988704a7fe
diff --git a/luminol-server/paper-patches/features/0016-Try-fixing-folia-spector-teleportation.patch b/luminol-server/paper-patches/features/0016-Try-fixing-folia-spector-teleportation.patch
new file mode 100644
index 0000000..fde25ad
--- /dev/null
+++ b/luminol-server/paper-patches/features/0016-Try-fixing-folia-spector-teleportation.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:53:24 +0800
+Subject: [PATCH] Try fixing folia spector teleportation
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..01f8c6ff3662569be5a4ff998bcd4fbbcb555105
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java
+@@ -0,0 +1,25 @@
++package me.earthme.luminol.config.modules.fixes;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class FoliaSpectorTeleportationFixConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled", comments =
++ """
++ The teleportation of spector players would call absMoveTo directly.\s
++ And when the camera teleported to another region,this would call absMoveTo\s
++ to let the spector player move to another region without any checks, which \s
++ would trigger the async catcher and crash the server""")
++ public static boolean fixSpectorTeleportFolia = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.FIXES;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "folia.fix_spector_teleportation";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch b/luminol-server/paper-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch
new file mode 100644
index 0000000..8db233e
--- /dev/null
+++ b/luminol-server/paper-patches/features/0017-Teleport-async-if-entity-was-moving-to-another-regio.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:53:42 +0800
+Subject: [PATCH] Teleport async if entity was moving to another region at once
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0e51d465db3554ac80d00c6b85cc1f013f3949ba
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaEntityMovingFixConfig.java
+@@ -0,0 +1,28 @@
++package me.earthme.luminol.config.modules.fixes;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class FoliaEntityMovingFixConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled", comments =
++ """
++ A simple fix of a issue on folia\s
++ (Some times 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""")
++ public static boolean enabled = false;
++ @ConfigInfo(baseName = "warn_on_detected")
++ public static boolean warnOnDetected = true;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.FIXES;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "folia.fix_high_velocity_issue";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch b/luminol-server/paper-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch
new file mode 100644
index 0000000..93522a6
--- /dev/null
+++ b/luminol-server/paper-patches/features/0018-Try-fixing-folia-off-region-POI-accessing-issue.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 10:57:00 +0800
+Subject: [PATCH] Try fixing folia off region POI accessing issue
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..7812a71f05dd32646037afd22cdabf72bb23b0d1
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java
+@@ -0,0 +1,25 @@
++package me.earthme.luminol.config.modules.fixes;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class FoliaPOIAccessOffRegionFixConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled", comments =
++ """
++ The POIManager of folia has something which has not been patched\s
++ for regionized ticking and these would trigger the async catcher\s
++ and make the server crash.If you would like to prevent it and didn't\s
++ mind the side effect(currently unknown), you can enable this""")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.FIXES;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "folia.fix_poi_access_off_region";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0019-Force-disable-builtin-spark-plugin.patch b/luminol-server/paper-patches/features/0019-Force-disable-builtin-spark-plugin.patch
new file mode 100644
index 0000000..8aa0f5e
--- /dev/null
+++ b/luminol-server/paper-patches/features/0019-Force-disable-builtin-spark-plugin.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:00:50 +0800
+Subject: [PATCH] Force disable builtin spark plugin
+
+
+diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
+index a0b84535a9d3833d4df692b85b272f145559dd80..c2ba46408b5ad727d7a17f21d47b2898bb1ef8b4 100644
+--- a/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
++++ b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
+@@ -87,7 +87,7 @@ public class FileProviderSource implements ProviderSource {
+ }
+
+ final PluginMeta config = type.getConfig(file);
+- if ((config.getName().equals("spark") && config.getMainClass().equals("me.lucko.spark.bukkit.BukkitSparkPlugin")) && !SparksFly.isPluginPreferred()) {
++ if ((config.getName().equals("spark") && config.getMainClass().equals("me.lucko.spark.bukkit.BukkitSparkPlugin")) && !SparksFly.isPluginPreferred() && false) { // Luminol - Force disable builtin spark
+ LOGGER.info("The spark plugin will not be loaded as this server bundles the spark profiler.");
+ return;
+ }
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+index f07330f3795dcd1162f9fc7aec8dd0f124f4daf2..cf4740f436fbcff73604ec7459001f2de15a45fe 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+@@ -312,7 +312,7 @@ public final class CraftServer implements Server {
+ public static Exception excessiveVelEx; // Paper - Velocity warnings
+ private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper
+ private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes
+- public final io.papermc.paper.SparksFly spark; // Paper - spark
++ public io.papermc.paper.SparksFly spark; // Paper - spark // Luminol - Force disable builtin spark
+
+ // Paper start - Folia region threading API
+ private final io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaRegionScheduler(); // Folia - region threading
+@@ -490,7 +490,7 @@ public final class CraftServer implements Server {
+ }
+ this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes
+ datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
+- this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark
++ if (false) this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark // Luminol - Force disable builtin spark
+ }
+
+ public boolean getCommandBlockOverride(String command) {
+@@ -1154,7 +1154,7 @@ public final class CraftServer implements Server {
+ this.reloadData();
+ org.spigotmc.SpigotConfig.registerCommands(); // Spigot
+ io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
+- this.spark.registerCommandBeforePlugins(this); // Paper - spark
++ if (false) this.spark.registerCommandBeforePlugins(this); // Paper - spark // Luminol - Force disable builtin spark
+ this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
+ this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
+
+@@ -1183,7 +1183,7 @@ public final class CraftServer implements Server {
+ this.loadPlugins();
+ this.enablePlugins(PluginLoadOrder.STARTUP);
+ this.enablePlugins(PluginLoadOrder.POSTWORLD);
+- this.spark.registerCommandAfterPlugins(this); // Paper - spark
++ if (false) this.spark.registerCommandAfterPlugins(this); // Paper - spark // Luminol - Force disable builtin spark
+ if (io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper != null) io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper.pluginsEnabled(); // Paper - Remap plugins
+ // Paper start - brigadier command API
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // to clear invalid state for event fire below
diff --git a/patches/server/0026-Set-old-pos-before-moving-entity-by-piston.patch b/luminol-server/paper-patches/features/0020-Set-old-pos-before-moving-entity-by-piston.patch
similarity index 54%
rename from patches/server/0026-Set-old-pos-before-moving-entity-by-piston.patch
rename to luminol-server/paper-patches/features/0020-Set-old-pos-before-moving-entity-by-piston.patch
index 182e4e2..8a99088 100644
--- a/patches/server/0026-Set-old-pos-before-moving-entity-by-piston.patch
+++ b/luminol-server/paper-patches/features/0020-Set-old-pos-before-moving-entity-by-piston.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 1 Jan 2025 12:18:18 +0800
+Date: Sun, 12 Jan 2025 11:02:07 +0800
Subject: [PATCH] Set old pos before moving entity by piston
@@ -30,15 +30,3 @@ index 0000000000000000000000000000000000000000..6edfb1d36a88d319151d28ba14873269
+ return "folia.fix_piston_moving_issue";
+ }
+}
-diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
-index c3a04ef842630b3df447dea48b84bccde0c89e83..9545f46c22cb7dcdf2412f9a741dc51be40faace 100644
---- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
-+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
-@@ -195,6 +195,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
-
- private static void moveEntityByPiston(Direction direction, Entity entity, double distance, Direction movementDirection) {
- NOCLIP.set(direction);
-+ if (me.earthme.luminol.config.modules.fixes.FoliaPistonIssueFixConfig.enabled) entity.setOldPosAndRot(); // Luminol- Try fixing folia issue #311
- entity.move(
- MoverType.PISTON,
- new Vec3(
diff --git a/patches/server/0030-Kaiiju-Entity-tick-and-removal-limiter.patch b/luminol-server/paper-patches/features/0021-Kaiiju-Entity-tick-and-removal-limiter.patch
similarity index 72%
rename from patches/server/0030-Kaiiju-Entity-tick-and-removal-limiter.patch
rename to luminol-server/paper-patches/features/0021-Kaiiju-Entity-tick-and-removal-limiter.patch
index c951fb9..8722e20 100644
--- a/patches/server/0030-Kaiiju-Entity-tick-and-removal-limiter.patch
+++ b/luminol-server/paper-patches/features/0021-Kaiiju-Entity-tick-and-removal-limiter.patch
@@ -1,21 +1,9 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Wed, 4 Dec 2024 23:39:18 +0800
+Date: Sun, 12 Jan 2025 11:07:09 +0800
Subject: [PATCH] Kaiiju Entity tick and removal limiter
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 8f23bf19618382ccf5fd10a0b17b57cd445dea58..4b79f96103c98896332113ffe5f0e22cf08ffdd1 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -27,6 +27,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
- dependencies {
- implementation(project(":luminol-api")) // Folia // Luminol
- implementation("com.electronwill.night-config:toml:3.6.6") // Luminol - Night config
-+ implementation("io.github.classgraph:classgraph:4.8.158") // Kaiiju - Entity throttling & Removal
- implementation("ca.spottedleaf:concurrentutil:0.0.2") // Paper - Add ConcurrentUtil dependency
- // Paper start
- implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityLimits.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityLimits.java
new file mode 100644
index 0000000000000000000000000000000000000000..40e80fc685a42bbaeea3e6e64754121178cc7d22
@@ -253,18 +241,6 @@ index 0000000000000000000000000000000000000000..eb690efacf083e4ff3e321578b12c534
+ }
+ }
+}
-diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
-index 1b741d4bccfd45beeec43300f44770516c0d850e..3c37ad27488486f9bb0f972369ccaee2284df673 100644
---- a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
-+++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java
-@@ -354,6 +354,7 @@ public final class RegionizedWorldData {
- private final IteratorSafeOrderedReferenceSet navigatingMobs = new IteratorSafeOrderedReferenceSet<>();
- public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
- public final ReferenceList trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
-+ public final dev.kaiijumc.kaiiju.KaiijuEntityThrottler entityThrottler = new dev.kaiijumc.kaiiju.KaiijuEntityThrottler(); // Kaiiju
-
- // block ticking
- private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>();
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/KaiijuEntityLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/KaiijuEntityLimiterConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..038d9ab60cfac7e40e7c0c0644fa0a0d035eac01
@@ -294,37 +270,3 @@ index 0000000000000000000000000000000000000000..038d9ab60cfac7e40e7c0c0644fa0a0d
+ KaiijuEntityLimits.init();
+ }
+}
-diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 07037eb601f9dcae2cad5f3e3d5f9a0ac142b68a..5503d506c595296ecad09a3ce4497a365f216af5 100644
---- a/src/main/java/net/minecraft/server/level/ServerLevel.java
-+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -811,6 +811,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
- }
-
- profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); try { // Folia - profiler
-+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterStart(); // Kaiiju
- org.spigotmc.ActivationRange.activateEntities(this); // Spigot
- } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); } // Folia - profiler
- profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); try { // Folia - profiler
-@@ -832,6 +833,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
- entity.stopRiding();
- }
-
-+ // Kaiiju start
-+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) {
-+ dev.kaiijumc.kaiiju.KaiijuEntityThrottler.EntityThrottlerReturn throttle = regionizedWorldData.entityThrottler.tickLimiterShouldSkip(entity);
-+ if (throttle.remove && !entity.hasCustomName()) entity.remove(Entity.RemovalReason.DISCARDED);
-+ if (throttle.skip) return;
-+ }
-+ // Kaiiju end
- gameprofilerfiller.push("tick");
- this.guardEntityTick(this::tickNonPassenger, entity);
- gameprofilerfiller.pop();
-@@ -839,6 +847,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
- }
- }
- });
-+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterFinish(regionizedWorldData); // Kaiiju
- } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); } // Folia - profiler
- gameprofilerfiller.pop();
- profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY); try { // Folia - profiler
diff --git a/luminol-server/paper-patches/features/0022-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch b/luminol-server/paper-patches/features/0022-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch
new file mode 100644
index 0000000..3a56735
--- /dev/null
+++ b/luminol-server/paper-patches/features/0022-KioCG-Chunk-API-and-display-of-chunkhot-in-tpsbar.patch
@@ -0,0 +1,201 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:29:51 +0800
+Subject: [PATCH] KioCG Chunk API and display of chunkhot in tpsbar
+
+
+diff --git a/src/main/java/com/kiocg/ChunkHot.java b/src/main/java/com/kiocg/ChunkHot.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..53b4397997bc9b9b9d88e48304b37a2590161906
+--- /dev/null
++++ b/src/main/java/com/kiocg/ChunkHot.java
+@@ -0,0 +1,90 @@
++package com.kiocg;
++
++import java.util.Arrays;
++
++public class ChunkHot {
++ // 热度统计总区间数量
++ private static final int TIMES_LENGTH = 10;
++ // 当前统计区间下标
++ private int index = -1;
++
++ // 热度统计区间
++ private final long[] times = new long[TIMES_LENGTH];
++ // 存放临时的区间数值
++ // 用于修正正在统计的当前区间热度没有计入总值的问题
++ private long temp;
++ // 所有区间的热度总值
++ private long total;
++
++ // 用于每个具体统计的计算
++ private long nanos;
++ // 当前统计是否进行中
++ private volatile boolean started = false;
++
++ /**
++ * 更新区间下标
++ */
++ public void nextTick() {
++ this.index = ++this.index % TIMES_LENGTH;
++ }
++
++ /**
++ * 开始统计一个新区间
++ */
++ public void start() {
++ started = true;
++ temp = times[this.index];
++ times[this.index] = 0L;
++ }
++
++ public boolean isStarted(){
++ return this.started;
++ }
++
++ /**
++ * 结束当前区间的统计
++ * 将统计值更新入热度总值
++ */
++ public void stop() {
++ started = false;
++ total -= temp;
++ total += times[this.index];
++ }
++
++ /**
++ * 开始一个具体统计
++ */
++ public void startTicking() {
++ if (!started) return;
++ nanos = System.nanoTime();
++ }
++
++ /**
++ * 结束一个具体统计
++ * 将统计值计入当前热度区间
++ */
++ public void stopTickingAndCount() {
++ if (!started) return;
++ // 定义一个具体统计的最大值为 1,000,000
++ // 有时候某个具体统计的计算值会在某1刻飙升,可能是由于保存数据到磁盘?
++ times[this.index] += Math.min(System.nanoTime() - nanos, 1000000L);
++ }
++
++ /**
++ * 清空统计 (当区块卸载时)
++ */
++ public void clear() {
++ started = false;
++ Arrays.fill(times, 0L);
++ temp = 0L;
++ total = 0L;
++ nanos = 0L;
++ }
++
++ /**
++ * @return 获取区块热度平均值
++ */
++ public long getAverage() {
++ return total / ((long) TIMES_LENGTH * 20L);
++ }
++}
+diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java
+index aafb2f5052c7c8e5971a47308253badb3027093c..9fe7ac7ba83bbcc9a2a851a5cace47641323f4d2 100644
+--- a/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java
++++ b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java
+@@ -12,11 +12,13 @@ public class TpsBarConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean tpsbarEnabled = false;
+ @ConfigInfo(baseName = "format")
+- public static String tpsBarFormat = "TPS: MSPT: Ping:ms";
++ public static String tpsBarFormat = "TPS: MSPT: Ping:ms ChunkHot:";
+ @ConfigInfo(baseName = "tps_color_list")
+ public static List tpsColors = List.of("GREEN","YELLOW","RED","PURPLE");
+ @ConfigInfo(baseName = "ping_color_list")
+ public static List pingColors = List.of("GREEN","YELLOW","RED","PURPLE");
++ @ConfigInfo(baseName = "chunkhot_color_list")
++ public static List chunkHotColors = List.of("GREEN","YELLOW","RED","PURPLE");
+ @ConfigInfo(baseName = "update_interval_ticks")
+ public static int updateInterval = 15;
+
+diff --git a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java
+index de2f03d6e771c09e8da2da454b7ec4a16c0a17ab..0b7347e8fdf995900221ee4aa4e97a4d260c6f9f 100644
+--- a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java
++++ b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java
+@@ -128,7 +128,8 @@ public class GlobalServerTpsBar {
+ TpsBarConfig.tpsBarFormat,
+ Placeholder.component("tps",getTpsComponent(tps)),
+ Placeholder.component("mspt",getMsptComponent(mspt)),
+- Placeholder.component("ping",getPingComponent(player.getPing()))
++ Placeholder.component("ping",getPingComponent(player.getPing())),
++ Placeholder.component("chunkhot",getChunkHotComponent(player.getNearbyChunkHot()))
+ ));
+ bar.color(barColorFromTps(tps));
+ bar.progress((float) Math.min((float)1,Math.max(mspt / 50,0)));
+@@ -170,6 +171,32 @@ public class GlobalServerTpsBar {
+ return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.format("%.2f", mspt)));
+ }
+
++ private static @NotNull Component getChunkHotComponent(long chunkHot){
++ final BossBar.Color colorBukkit = barColorFromChunkHot(chunkHot);
++ final String colorString = colorBukkit.name();
++
++ final String content = "<%s>%s>";
++ final String replaced = String.format(content,colorString,colorString);
++
++ return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.valueOf(chunkHot)));
++ }
++
++ private static BossBar.Color barColorFromChunkHot(long chunkHot){
++ if (chunkHot == -1){
++ return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(3));
++ }
++
++ if (chunkHot <= 300000L){
++ return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(0));
++ }
++
++ if (chunkHot <= 500000L){
++ return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(1));
++ }
++
++ return BossBar.Color.valueOf(TpsBarConfig.chunkHotColors.get(2));
++ }
++
+ private static BossBar.Color barColorFromMspt(double mspt){
+ if (mspt == -1){
+ return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3));
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+index de8b9048c8395c05b8688bc9d984b8ad680f15b3..f42692cd4f0154705c3d5b030d281cfc333803ed 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+@@ -437,4 +437,12 @@ public class CraftChunk implements Chunk {
+ static {
+ Arrays.fill(FULL_LIGHT, (byte) 0xFF);
+ }
++
++ // KioCG start - ChunkHot
++ @Override
++ public long getChunkHotAvg() {
++ final net.minecraft.world.level.chunk.LevelChunk target = this.worldServer.getChunkIfLoaded(this.x,this.z);
++ return target == null ? -1 : target.getChunkHot().getAverage();
++ }
++ // KioCG end
+ }
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 39ac96a61e48750a420ea612e37e3f8195569f10..f6da4c065e362db093a882edbb3238ec48cb7999 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+@@ -3565,4 +3565,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData()));
+ }
+ // Paper end - entity effect API
++
++ // KioCG start - ChunkHot
++ @Override
++ public long getNearbyChunkHot() {
++ return this.getHandle().getNearbyChunkHot();
++ }
++ // KioCG end
+ }
diff --git a/luminol-server/paper-patches/features/0023-Purpur-use-alternative-keep-alive.patch b/luminol-server/paper-patches/features/0023-Purpur-use-alternative-keep-alive.patch
new file mode 100644
index 0000000..9eaebc9
--- /dev/null
+++ b/luminol-server/paper-patches/features/0023-Purpur-use-alternative-keep-alive.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 11:43:17 +0800
+Subject: [PATCH] Purpur use alternative keep alive
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/PurpurAlternativeKeepaliveConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/PurpurAlternativeKeepaliveConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..43bbc2c30bdd3872a0179e0070403c3e257c320e
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/PurpurAlternativeKeepaliveConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.optimizations;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class PurpurAlternativeKeepaliveConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean useAlternateKeepAlive = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.OPTIMIZATIONS;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "alternative_keepalive_handling";
++ }
++}
diff --git a/patches/server/0031-Petal-Reduce-sensor-work.patch b/luminol-server/paper-patches/features/0024-Petal-Reduce-sensor-work.patch
similarity index 50%
rename from patches/server/0031-Petal-Reduce-sensor-work.patch
rename to luminol-server/paper-patches/features/0024-Petal-Reduce-sensor-work.patch
index b9618e3..f2cd0cf 100644
--- a/patches/server/0031-Petal-Reduce-sensor-work.patch
+++ b/luminol-server/paper-patches/features/0024-Petal-Reduce-sensor-work.patch
@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269
-Date: Sat, 30 Nov 2024 11:50:09 +0800
+Date: Sun, 12 Jan 2025 12:22:00 +0800
Subject: [PATCH] Petal Reduce sensor work
@@ -32,22 +32,3 @@ index 0000000000000000000000000000000000000000..dd45cf1fde5ee4cf8347064f106c64b8
+ return "reduce_sensor_work";
+ }
+}
-diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
-index e48728723e9f765099fc1cea8e6a2baa48d7fc75..6b66d73daa0145829cd964403e7958335ef0aa9a 100644
---- a/src/main/java/net/minecraft/world/entity/Mob.java
-+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -930,12 +930,12 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
- return;
- }
- // Paper end - Allow nerfed mobs to jump and float
-+ int i = this.tickCount + this.getId(); //Luminol - Petal - Move up
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("sensing");
-- this.sensing.tick();
-+ if (i % me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.delayTicks == 0 || !me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.enabled) this.sensing.tick(); // Luminol - Petal - Reduce sensor work
- gameprofilerfiller.pop();
-- int i = this.tickCount + this.getId();
-
- if (i % 2 != 0 && this.tickCount > 1) {
- gameprofilerfiller.push("targetSelector");
diff --git a/luminol-server/paper-patches/features/0025-Pufferfish-Reduce-projectile-chunk-loading.patch b/luminol-server/paper-patches/features/0025-Pufferfish-Reduce-projectile-chunk-loading.patch
new file mode 100644
index 0000000..146948a
--- /dev/null
+++ b/luminol-server/paper-patches/features/0025-Pufferfish-Reduce-projectile-chunk-loading.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:29:28 +0800
+Subject: [PATCH] Pufferfish Reduce projectile chunk loading
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..12683ec5a5102e45b6171fea0b833ba57e5e188c
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java
+@@ -0,0 +1,22 @@
++package me.earthme.luminol.config.modules.optimizations;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class ProjectileChunkReduceConfig implements IConfigModule {
++ @ConfigInfo(baseName = "max-loads-per-tick")
++ public static int maxProjectileLoadsPerTick;
++ @ConfigInfo(baseName = "max-loads-per-projectile")
++ public static int maxProjectileLoadsPerProjectile;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.OPTIMIZATIONS;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "projectile";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0026-Pufferfish-Optimize-suffocation.patch b/luminol-server/paper-patches/features/0026-Pufferfish-Optimize-suffocation.patch
new file mode 100644
index 0000000..d0c9e1b
--- /dev/null
+++ b/luminol-server/paper-patches/features/0026-Pufferfish-Optimize-suffocation.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:30:50 +0800
+Subject: [PATCH] Pufferfish Optimize suffocation
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..3e48cd297b4869e5c89b6abc43c726d3a7511e7f
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.optimizations;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class SuffocationOptimizationConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.OPTIMIZATIONS;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "suffocation_optimization";
++ }
++}
diff --git a/luminol-server/paper-patches/features/0027-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch b/luminol-server/paper-patches/features/0027-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch
new file mode 100644
index 0000000..bce2177
--- /dev/null
+++ b/luminol-server/paper-patches/features/0027-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MrHua269
+Date: Sun, 12 Jan 2025 12:34:05 +0800
+Subject: [PATCH] Pufferfish Throttle goal selector during inactive ticking
+
+
+diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..acc032f727e605e79b688efb4873ff474fe7e132
+--- /dev/null
++++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java
+@@ -0,0 +1,20 @@
++package me.earthme.luminol.config.modules.optimizations;
++
++import me.earthme.luminol.config.ConfigInfo;
++import me.earthme.luminol.config.EnumConfigCategory;
++import me.earthme.luminol.config.IConfigModule;
++
++public class EntityGoalSelectorInactiveTickConfig implements IConfigModule {
++ @ConfigInfo(baseName = "enabled")
++ public static boolean enabled = false;
++
++ @Override
++ public EnumConfigCategory getCategory() {
++ return EnumConfigCategory.OPTIMIZATIONS;
++ }
++
++ @Override
++ public String getBaseName() {
++ return "skip_goal_selector_tick_in_inactive_tick";
++ }
++}
diff --git a/luminol-server/paper-patches/files/src/main/resources/data/.paperassetsroot.patch b/luminol-server/paper-patches/files/src/main/resources/data/.paperassetsroot.patch
new file mode 100644
index 0000000..b41d58b
--- /dev/null
+++ b/luminol-server/paper-patches/files/src/main/resources/data/.paperassetsroot.patch
@@ -0,0 +1,3 @@
+--- a/src/main/resources/data/.paperassetsroot
++++ b/src/main/resources/data/.paperassetsroot
+@@ -1,0 +_,0 @@
diff --git a/patches/api/0002-Threaded-region-start-tick-and-finished-tick-event.patch b/patches/api/0002-Threaded-region-start-tick-and-finished-tick-event.patch
deleted file mode 100644
index 02603d2..0000000
--- a/patches/api/0002-Threaded-region-start-tick-and-finished-tick-event.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Fri, 9 Feb 2024 03:32:05 +0000
-Subject: [PATCH] Threaded region start tick and finished tick event
-
-
-diff --git a/src/main/java/me/earthme/luminol/api/events/TickRegionFinishedTickEvent.java b/src/main/java/me/earthme/luminol/api/events/TickRegionFinishedTickEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..29b98728d3ca4a439c6b3333cd123c0e0b8a2846
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/api/events/TickRegionFinishedTickEvent.java
-@@ -0,0 +1,42 @@
-+package me.earthme.luminol.api.events;
-+
-+import org.bukkit.event.Event;
-+import org.bukkit.event.HandlerList;
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Called when a region finished its tick task.
-+ */
-+public class TickRegionFinishedTickEvent extends Event {
-+ private static final HandlerList handlers = new HandlerList();
-+
-+ private final long currTime;
-+ private final long regionId;
-+
-+ public TickRegionFinishedTickEvent(long currTime, long regionId) {
-+ this.currTime = currTime;
-+ this.regionId = regionId;
-+ }
-+
-+ /**
-+ * Get the time of tick end
-+ * @return The time of tick end in nanoseconds
-+ */
-+ public long getFinishedTime() {
-+ return this.currTime;
-+ }
-+
-+ /**
-+ * Get the id of current region
-+ * Notice: The id of global region is -1 in this event
-+ * @return The id of current region
-+ */
-+ public long getRegionId() {
-+ return this.regionId;
-+ }
-+
-+ @Override
-+ public @NotNull HandlerList getHandlers() {
-+ return handlers;
-+ }
-+}
-diff --git a/src/main/java/me/earthme/luminol/api/events/TickRegionStartTickEvent.java b/src/main/java/me/earthme/luminol/api/events/TickRegionStartTickEvent.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..1f3cba43ebd873965c24b96ca116abfb149ab4e6
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/api/events/TickRegionStartTickEvent.java
-@@ -0,0 +1,41 @@
-+package me.earthme.luminol.api.events;
-+
-+import org.bukkit.event.Event;
-+import org.bukkit.event.HandlerList;
-+import org.jetbrains.annotations.NotNull;
-+
-+/**
-+ * Called when a tick was started.
-+ */
-+public class TickRegionStartTickEvent extends Event {
-+ private static final HandlerList handlers = new HandlerList();
-+ private final long currTime;
-+ private final long regionId;
-+
-+ public TickRegionStartTickEvent(long currTime, long regionId) {
-+ this.currTime = currTime;
-+ this.regionId = regionId;
-+ }
-+
-+ /**
-+ * Get the id of current region
-+ * Notice: The id of global region is -1 in this event
-+ * @return The id of current region
-+ */
-+ public long getRegionId() {
-+ return this.regionId;
-+ }
-+
-+ /**
-+ * Get the time of tick start
-+ * @return The time of tick start in nanoseconds
-+ */
-+ public long getStartTime(){
-+ return this.currTime;
-+ }
-+
-+ @Override
-+ public @NotNull HandlerList getHandlers() {
-+ return handlers;
-+ }
-+}
diff --git a/patches/api/0004-FoliaPR-Add-TPS-From-Region.patch b/patches/api/0004-FoliaPR-Add-TPS-From-Region.patch
deleted file mode 100644
index 5850ba0..0000000
--- a/patches/api/0004-FoliaPR-Add-TPS-From-Region.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Tue, 30 Jul 2024 17:58:25 +0800
-Subject: [PATCH] FoliaPR Add TPS From Region
-
-
-diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
-index 5ce98e09e9bfcae45896401c69578aa879222893..dacb9342f21ba045b97f004c6c9970adbc2b9eb5 100644
---- a/src/main/java/org/bukkit/Bukkit.java
-+++ b/src/main/java/org/bukkit/Bukkit.java
-@@ -2429,6 +2429,28 @@ public final class Bukkit {
- }
- // Paper end
-
-+ // Folia start
-+ /**
-+ * Gets the current location TPS.
-+ *
-+ * @param location the location for which to get the TPS
-+ * @return current location TPS (5s, 15s, 1m, 5m, 15m in Folia-Server), or null if the region doesn't exist
-+ */
-+ public double @Nullable [] getTPS(Location location) {
-+ return server.getTPS(location);
-+ }
-+
-+ /**
-+ * Gets the current chunk TPS.
-+ *
-+ * @param chunk the chunk for which to get the TPS
-+ * @return current chunk TPS (5s, 15s, 1m, 5m, 15m in Folia-Server), or null if the region doesn't exist
-+ */
-+ public double @Nullable [] getTPS(Chunk chunk){
-+ return server.getTPS(chunk);
-+ }
-+ // Folia end
-+
- /**
- * Get the advancement specified by this key.
- *
-diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index a92bd4da6788f1331a4838ab5760baec2dc6e8ec..32ec411df95dbce73700ce47fb24737f1f508bb5 100644
---- a/src/main/java/org/bukkit/Server.java
-+++ b/src/main/java/org/bukkit/Server.java
-@@ -2076,6 +2076,24 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
- double getAverageTickTime();
- // Paper end
-
-+ // Folia start
-+ /**
-+ * Gets the current location TPS.
-+ *
-+ * @param location the location for which to get the TPS
-+ * @return current location TPS (5s, 15s, 1m, 5m, 15m in Folia-Server), or null if the region doesn't exist
-+ */
-+ public double @Nullable [] getTPS(Location location);
-+
-+ /**
-+ * Gets the current chunk TPS.
-+ *
-+ * @param chunk the chunk for which to get the TPS
-+ * @return current chunk TPS (5s, 15s, 1m, 5m, 15m in Folia-Server), or null if the region doesn't exist
-+ */
-+ public double @Nullable [] getTPS(Chunk chunk);
-+ // Folia end
-+
- // Paper start
- /**
- * Gets the active {@link org.bukkit.command.CommandMap}
diff --git a/patches/api/0005-Pufferfish-SIMD-Utilities.patch b/patches/api/0005-Pufferfish-SIMD-Utilities.patch
deleted file mode 100644
index 19f854a..0000000
--- a/patches/api/0005-Pufferfish-SIMD-Utilities.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Tue, 6 Aug 2024 14:32:22 +0800
-Subject: [PATCH] Pufferfish SIMD Utilities
-
-
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 571534b42cd9c33d6a7bb6fe3bf3a28e33f8e5de..1aa76451f9129b578d6887b1239966eb67f5ee1b 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -150,6 +150,13 @@ val generateApiVersioningFile by tasks.registering {
- }
- }
-
-+// Pufferfish Start
-+tasks.withType {
-+ val compilerArgs = options.compilerArgs
-+ compilerArgs.add("--add-modules=jdk.incubator.vector")
-+}
-+// Pufferfish End
-+
- tasks.jar {
- from(generateApiVersioningFile.map { it.outputs.files.singleFile }) {
- into("META-INF/maven/${project.group}/${project.name}")
-@@ -209,6 +216,7 @@ tasks.withType {
- into("build/docs/javadoc")
- }
- }
-+ options.addStringOption("-add-modules", "jdk.incubator.vector") // Pufferfish - SIMD support
- }
-
- tasks.test {
-diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9b5b32cd9
---- /dev/null
-+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
-@@ -0,0 +1,39 @@
-+package gg.pufferfish.pufferfish.simd;
-+
-+import jdk.incubator.vector.FloatVector;
-+import jdk.incubator.vector.IntVector;
-+import jdk.incubator.vector.VectorSpecies;
-+import org.slf4j.Logger;
-+
-+/**
-+ * Basically, java is annoying and we have to push this out to its own class.
-+ */
-+@Deprecated
-+public class SIMDChecker {
-+
-+ @Deprecated
-+ public static boolean canEnable(Logger logger) {
-+ try {
-+ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) {
-+ return false;
-+ } else {
-+ SIMDDetection.testRun = true;
-+
-+ VectorSpecies ISPEC = IntVector.SPECIES_PREFERRED;
-+ VectorSpecies FSPEC = FloatVector.SPECIES_PREFERRED;
-+
-+ logger.info("Max SIMD vector size on this system is {} bits (int)", ISPEC.vectorBitSize());
-+ logger.info("Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)");
-+
-+ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) {
-+ logger.warn("SIMD is not properly supported on this system!");
-+ return false;
-+ }
-+
-+ return true;
-+ }
-+ } catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it.
-+ return false;
-+ }
-+
-+}
-diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae26c5567b
---- /dev/null
-+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java
-@@ -0,0 +1,35 @@
-+package gg.pufferfish.pufferfish.simd;
-+
-+import org.slf4j.Logger;
-+
-+@Deprecated
-+public class SIMDDetection {
-+
-+ public static boolean isEnabled = false;
-+ public static boolean versionLimited = false;
-+ public static boolean testRun = false;
-+
-+ @Deprecated
-+ public static boolean canEnable(Logger logger) {
-+ try {
-+ return SIMDChecker.canEnable(logger);
-+ } catch (NoClassDefFoundError | Exception ignored) {
-+ return false;
-+ }
-+ }
-+
-+ @Deprecated
-+ public static int getJavaVersion() {
-+ // https://stackoverflow.com/a/2591122
-+ String version = System.getProperty("java.version");
-+ if(version.startsWith("1.")) {
-+ version = version.substring(2, 3);
-+ } else {
-+ int dot = version.indexOf(".");
-+ if(dot != -1) { version = version.substring(0, dot); }
-+ }
-+ version = version.split("-")[0]; // Azul is stupid
-+ return Integer.parseInt(version);
-+ }
-+
-+}
diff --git a/patches/api/0007-Pufferfish-Sentry.patch b/patches/api/0007-Pufferfish-Sentry.patch
deleted file mode 100644
index 7872724..0000000
--- a/patches/api/0007-Pufferfish-Sentry.patch
+++ /dev/null
@@ -1,243 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: adabugra <57899270+adabugra@users.noreply.github.com>
-Date: Mon, 6 Jan 2025 19:24:06 +0300
-Subject: [PATCH] Pufferfish: Sentry
-
-
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 1aa76451f9129b578d6887b1239966eb67f5ee1b..2ddad10cf12dd07fd227ddda13336fdd61cd0197 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -66,6 +66,7 @@ dependencies {
- apiAndDocs("net.kyori:adventure-text-logger-slf4j")
- api("org.apache.logging.log4j:log4j-api:$log4jVersion")
- api("org.slf4j:slf4j-api:$slf4jVersion")
-+ api("io.sentry:sentry:8.0.0-rc.2") // Pufferfish
-
- implementation("org.ow2.asm:asm:9.7.1")
- implementation("org.ow2.asm:asm-commons:9.7.1")
-diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..c7772aac00f6db664f7a5673bc2585fa025e6aad
---- /dev/null
-+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
-@@ -0,0 +1,165 @@
-+package gg.pufferfish.pufferfish.sentry;
-+
-+import com.google.gson.Gson;
-+
-+import java.lang.reflect.Field;
-+import java.lang.reflect.Modifier;
-+import java.util.Map;
-+import java.util.TreeMap;
-+
-+import org.apache.logging.log4j.ThreadContext;
-+import org.bukkit.command.Command;
-+import org.bukkit.command.CommandSender;
-+import org.bukkit.entity.Player;
-+import org.bukkit.event.Event;
-+import org.bukkit.event.player.PlayerEvent;
-+import org.bukkit.plugin.Plugin;
-+import org.bukkit.plugin.RegisteredListener;
-+import org.jetbrains.annotations.Nullable;
-+
-+public class SentryContext {
-+
-+ private static final Gson GSON = new Gson();
-+
-+ public static void setPluginContext(@Nullable Plugin plugin) {
-+ if (plugin != null) {
-+ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName());
-+ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getPluginMeta().getVersion());
-+ }
-+ }
-+
-+ public static void removePluginContext() {
-+ ThreadContext.remove("pufferfishsentry_pluginname");
-+ ThreadContext.remove("pufferfishsentry_pluginversion");
-+ }
-+
-+ public static void setSenderContext(@Nullable CommandSender sender) {
-+ if (sender != null) {
-+ ThreadContext.put("pufferfishsentry_playername", sender.getName());
-+ if (sender instanceof Player player) {
-+ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString());
-+ }
-+ }
-+ }
-+
-+ public static void removeSenderContext() {
-+ ThreadContext.remove("pufferfishsentry_playername");
-+ ThreadContext.remove("pufferfishsentry_playerid");
-+ }
-+
-+ public static void setEventContext(Event event, RegisteredListener registration) {
-+ setPluginContext(registration.getPlugin());
-+
-+ try {
-+ // Find the player that was involved with this event
-+ Player player = null;
-+ if (event instanceof PlayerEvent) {
-+ player = ((PlayerEvent) event).getPlayer();
-+ } else {
-+ Class extends Event> eventClass = event.getClass();
-+
-+ Field playerField = null;
-+
-+ for (Field field : eventClass.getDeclaredFields()) {
-+ if (field.getType().equals(Player.class)) {
-+ playerField = field;
-+ break;
-+ }
-+ }
-+
-+ if (playerField != null) {
-+ playerField.setAccessible(true);
-+ player = (Player) playerField.get(event);
-+ }
-+ }
-+
-+ if (player != null) {
-+ setSenderContext(player);
-+ }
-+ } catch (Exception ignored) {
-+ } // We can't really safely log exceptions.
-+
-+ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event)));
-+ }
-+
-+ public static void removeEventContext() {
-+ removePluginContext();
-+ removeSenderContext();
-+ ThreadContext.remove("pufferfishsentry_eventdata");
-+ }
-+
-+ private static Map serializeFields(Object object) {
-+ Map fields = new TreeMap<>();
-+ fields.put("_class", object.getClass().getName());
-+ for (Field declaredField : object.getClass().getDeclaredFields()) {
-+ try {
-+ if (Modifier.isStatic(declaredField.getModifiers())) {
-+ continue;
-+ }
-+
-+ String fieldName = declaredField.getName();
-+ if (fieldName.equals("handlers")) {
-+ continue;
-+ }
-+ declaredField.setAccessible(true);
-+ Object value = declaredField.get(object);
-+ if (value != null) {
-+ fields.put(fieldName, value.toString());
-+ } else {
-+ fields.put(fieldName, "");
-+ }
-+ } catch (Exception ignored) {
-+ } // We can't really safely log exceptions.
-+ }
-+ return fields;
-+ }
-+
-+ public static class State {
-+
-+ private Plugin plugin;
-+ private Command command;
-+ private String commandLine;
-+ private Event event;
-+ private RegisteredListener registeredListener;
-+
-+ public Plugin getPlugin() {
-+ return plugin;
-+ }
-+
-+ public void setPlugin(Plugin plugin) {
-+ this.plugin = plugin;
-+ }
-+
-+ public Command getCommand() {
-+ return command;
-+ }
-+
-+ public void setCommand(Command command) {
-+ this.command = command;
-+ }
-+
-+ public String getCommandLine() {
-+ return commandLine;
-+ }
-+
-+ public void setCommandLine(String commandLine) {
-+ this.commandLine = commandLine;
-+ }
-+
-+ public Event getEvent() {
-+ return event;
-+ }
-+
-+ public void setEvent(Event event) {
-+ this.event = event;
-+ }
-+
-+ public RegisteredListener getRegisteredListener() {
-+ return registeredListener;
-+ }
-+
-+ public void setRegisteredListener(RegisteredListener registeredListener) {
-+ this.registeredListener = registeredListener;
-+ }
-+ }
-+}
-diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index ab36e3aaff57e2f27b5aed06b4bdfe277f86a35e..96da9f1082ab134d197b3a6069f2fcdf38585efe 100644
---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-@@ -597,7 +597,9 @@ public final class SimplePluginManager implements PluginManager {
-
- // Paper start
- private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
-+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
- server.getLogger().log(Level.SEVERE, msg, ex);
-+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
- callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));
- }
- // Paper end
-@@ -667,9 +669,11 @@ public final class SimplePluginManager implements PluginManager {
- ));
- }
- } catch (Throwable ex) {
-+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish
- // Paper start - error reporting
- String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
- server.getLogger().log(Level.SEVERE, msg, ex);
-+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish
- if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop
- callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event)));
- }
-diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-index b412aaf08901d169ac9fc89b36f9d6ccb95c53d3..45a9ca8969f635d20cc44c062fda85bbccd8f8ff 100644
---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-@@ -336,7 +336,13 @@ public final class JavaPluginLoader implements PluginLoader {
- try {
- jPlugin.setEnabled(true);
- } catch (Throwable ex) {
-+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
- server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
-+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
-+ // Paper start - Disable plugins that fail to load
-+ this.server.getPluginManager().disablePlugin(jPlugin);
-+ return;
-+ // Paper end
- }
-
- // Perhaps abort here, rather than continue going, but as it stands,
-@@ -361,7 +367,9 @@ public final class JavaPluginLoader implements PluginLoader {
- try {
- jPlugin.setEnabled(false);
- } catch (Throwable ex) {
-+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
- server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
-+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
- }
-
- if (cloader instanceof PluginClassLoader) {
diff --git a/patches/server/0001-Fix-build.patch b/patches/server/0001-Fix-build.patch
deleted file mode 100644
index 1570e4c..0000000
--- a/patches/server/0001-Fix-build.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 4 Dec 2024 23:04:00 +0800
-Subject: [PATCH] Fix build
-
-
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 8d2b5fec6fe27dca3ce01ba1ce50506179fc3b4d..dd6cc4972a209e58313a2b6c6fe87c3605fe34ae 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -25,7 +25,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider {
- // Paper end - configure mockito agent that is needed in newer java versions
-
- dependencies {
-- implementation(project(":folia-api")) // Folia
-+ implementation(project(":luminol-api")) // Folia // Luminol
- implementation("ca.spottedleaf:concurrentutil:0.0.2") // Paper - Add ConcurrentUtil dependency
- // Paper start
- implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
diff --git a/patches/server/0005-Add-config-for-unsafe-teleportation.patch b/patches/server/0005-Add-config-for-unsafe-teleportation.patch
deleted file mode 100644
index 0c120f9..0000000
--- a/patches/server/0005-Add-config-for-unsafe-teleportation.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:26:36 +0800
-Subject: [PATCH] Add config for unsafe teleportation
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..865ffe0051d84ac9018ab54a54894c2fe8fd573e
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
-@@ -0,0 +1,22 @@
-+package me.earthme.luminol.config.modules.fixes;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class UnsafeTeleportationConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled", comments = "Allow non player entities enter end portals if enabled.\n" +
-+ "If you want to use sand duping,please turn on this.\n" +
-+ "Warning: This would cause some unsafe issues, you could learn more on : https://github.com/PaperMC/Folia/issues/297")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.FIXES;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "allow_unsafe_teleportation";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
-index a498cdbe42df3161c35b2a1652dfa63693366bd6..76e8eca1229430742c6c2557d481fb98c570a8bc 100644
---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
-+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
-@@ -69,7 +69,7 @@ public class FallingBlockEntity extends Entity {
- public float fallDamagePerDistance;
- @Nullable
- public CompoundTag blockData;
-- public boolean forceTickAfterTeleportToDuplicate;
-+ public boolean forceTickAfterTeleportToDuplicate = me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled; // Luminol - Unsafe teleportation
- protected static final EntityDataAccessor DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
- public boolean autoExpire = true; // Paper - Expand FallingBlock API
-
-@@ -430,7 +430,7 @@ public class FallingBlockEntity extends Entity {
- boolean flag = (resourcekey1 == Level.END || resourcekey == Level.END) && resourcekey1 != resourcekey;
- Entity entity = super.teleport(teleportTarget);
-
-- this.forceTickAfterTeleportToDuplicate = entity != null && flag && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper
-+ this.forceTickAfterTeleportToDuplicate = entity != null && flag && (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation || me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled); // Paper // Luminol - Unsafe teleportation
- return entity;
- }
- }
-diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
-index 45b8ac1418864ea32bd625b0d57fcec288ea5b0c..96dfc7062c2b0d371717c2042bf7c8e8b32e8716 100644
---- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
-+++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java
-@@ -76,7 +76,11 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
- if (event.isCancelled()) return; // Paper - make cancellable
- // CraftBukkit end
- // Folia - region threading - do not show credits
--
-+ // Luminol start - unsafe teleportation
-+ if (me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled && !(entity instanceof net.minecraft.world.entity.player.Player)) {
-+ entity.endPortalLogicAsync(pos);
-+ }
-+ // Luminol end
- entity.setAsInsidePortal(this, pos);
- }
-
diff --git a/patches/server/0007-Add-config-for-chat-sign.patch b/patches/server/0007-Add-config-for-chat-sign.patch
deleted file mode 100644
index 3e6df2e..0000000
--- a/patches/server/0007-Add-config-for-chat-sign.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 7 Feb 2024 02:00:50 +0000
-Subject: [PATCH] Add config for chat sign
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ChatSignConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ChatSignConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..1e03e51e51f56c38abaad100274e25c9f854f727
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ChatSignConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class ChatSignConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "mojang_chat_sign";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/commands/arguments/ArgumentSignatures.java b/src/main/java/net/minecraft/commands/arguments/ArgumentSignatures.java
-index 479e6e2aa88a22ef7f8fccb06add6806f5b71d9d..22dae23a0c2fa4c85befd670637b1e592d889b58 100644
---- a/src/main/java/net/minecraft/commands/arguments/ArgumentSignatures.java
-+++ b/src/main/java/net/minecraft/commands/arguments/ArgumentSignatures.java
-@@ -14,9 +14,16 @@ public record ArgumentSignatures(List entries) {
- private static final int MAX_ARGUMENT_NAME_LENGTH = 16;
-
- public ArgumentSignatures(FriendlyByteBuf buf) {
-- this(buf.readCollection(FriendlyByteBuf.limitValue(ArrayList::new, 8), ArgumentSignatures.Entry::new));
-+ this(readSign(buf)); //Luminol - Fix java compile
- }
-
-+ //Luminol start - Add config for chat sign
-+ private static List readSign(FriendlyByteBuf buf) {
-+ var entries = buf.readCollection(FriendlyByteBuf.limitValue(ArrayList::new, 8), Entry::new);
-+ return me.earthme.luminol.config.modules.misc.ChatSignConfig.enabled ? List.of() : entries;
-+ }
-+ //Luminol end
-+
- public void write(FriendlyByteBuf buf) {
- buf.writeCollection(this.entries, (buf2, entry) -> entry.write(buf2));
- }
-diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
-index a523a83aec3a6ecbec4d60a187edc0c0167d15b4..324df3cce3f5a1ab6b4d2acfbb8e80aa551870d7 100644
---- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
-+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
-@@ -129,6 +129,16 @@ public class FriendlyByteBuf extends ByteBuf {
- // Paper end - Adventure; add max length parameter
- DataResult dataresult = codec.encodeStart(JsonOps.INSTANCE, value);
-
-+ //Luminol start - Add config for chat sign
-+ if (codec == net.minecraft.network.protocol.status.ServerStatus.CODEC) {
-+ JsonElement element = dataresult.getOrThrow(string -> new EncoderException("Failed to encode: " + string + " " + value));
-+ element.getAsJsonObject().addProperty("preventsChatReports", !me.earthme.luminol.config.modules.misc.ChatSignConfig.enabled);
-+
-+ this.writeUtf(GSON.toJson(element));
-+ return;
-+ }
-+ //Luminol end
-+
- this.writeUtf(FriendlyByteBuf.GSON.toJson((JsonElement) dataresult.getOrThrow((s) -> {
- return new EncoderException("Failed to encode: " + s + " " + String.valueOf(value));
- })), maxLength); // Paper - Adventure; add max length parameter
diff --git a/patches/server/0010-Add-config-for-username-check.patch b/patches/server/0010-Add-config-for-username-check.patch
deleted file mode 100644
index 6aba5be..0000000
--- a/patches/server/0010-Add-config-for-username-check.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 7 Feb 2024 04:50:10 +0000
-Subject: [PATCH] Add config for username check
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..c7e4724cc4ab8d911bcaf0106c098b266c843bb1
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class UsernameCheckConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "username_checks";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-index 227d62a69a453d49c28568ecb41ecef85a35405b..8951397adcc5505304d0dece6435aab786017399 100644
---- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-@@ -178,7 +178,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
- public void handleHello(ServerboundHelloPacket packet) {
- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
- // Paper start - Validate usernames
-- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
-+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled // Luminol - Add config for username check
-+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
- && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
- && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
- Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username", new Object[0]);
-diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
-index 34b4166adfae8ff7d1eb73d56a72931b005330a7..fc95632268caa8941dcce7a575ce00303864c4c1 100644
---- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
-+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
-@@ -82,7 +82,7 @@ public class GameProfileCache {
- }
-
- private static Optional lookupGameProfile(GameProfileRepository repository, String name) {
-- if (!StringUtil.isValidPlayerName(name)) {
-+ if (!StringUtil.isValidPlayerName(name, false)) { // Luminol - Add config for username check - Directly return, skip unnecessary following logic
- return GameProfileCache.createUnknownProfile(name);
- } else {
- final AtomicReference atomicreference = new AtomicReference();
-diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java
-index 6c33002dc8bbb3759c3156302ab7d1f26ce5e8ee..8caf8dd187dfdc67a8b97db080a9fe0ef5234943 100644
---- a/src/main/java/net/minecraft/util/StringUtil.java
-+++ b/src/main/java/net/minecraft/util/StringUtil.java
-@@ -64,6 +64,13 @@ public class StringUtil {
- }
-
- public static boolean isValidPlayerName(String name) {
-+ // Luminol start - Add config for username check
-+ return isValidPlayerName(name, !me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled);
-+ }
-+
-+ public static boolean isValidPlayerName(String name, boolean bypassCheck) {
-+ if (bypassCheck) return name.length() <= 16;
-+ // Luminol end - Add config for username check
- return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
- }
-
diff --git a/patches/server/0011-Add-config-for-offline-mode-warning.patch b/patches/server/0011-Add-config-for-offline-mode-warning.patch
deleted file mode 100644
index c017850..0000000
--- a/patches/server/0011-Add-config-for-offline-mode-warning.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 7 Feb 2024 06:40:44 +0000
-Subject: [PATCH] Add config for offline mode warning
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..502b93c7bda9e8577a1901a8777b7cf9b9bdc36b
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/OfflineModeWarningConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class OfflineModeWarningConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "warn_on_offline_mode";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index 4ff5105d32c41a8ea145e7833ea6a3cee0108031..295504dab771c8bb8c668545fe5d62eae0561b76 100644
---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -297,7 +297,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
- String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord";
- String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/";
- // Paper end - Add Velocity IP Forwarding Support
-- if (!this.usesAuthentication()) {
-+ if (!this.usesAuthentication() && me.earthme.luminol.config.modules.misc.OfflineModeWarningConfig.enabled) { //Luminol - Add config for offline mod warning
- DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
- DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
- // Spigot start
diff --git a/patches/server/0012-Add-config-for-out-of-order-chat-checks.patch b/patches/server/0012-Add-config-for-out-of-order-chat-checks.patch
deleted file mode 100644
index 4e8dcce..0000000
--- a/patches/server/0012-Add-config-for-out-of-order-chat-checks.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Tue, 20 Feb 2024 13:10:07 +0000
-Subject: [PATCH] Add config for out-of-order chat checks
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..83176a8a7e993b51a0663b0f76161884abbf4951
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/InorderChatConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class InorderChatConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "mojang_out_of_order_chat_check";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
-index 300929a406905f5ff1ede664d5b99fb0938d4d2e..7c82730e9a66f9b44dd559d7b8da511f9c5f8ca8 100644
---- a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
-+++ b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
-@@ -45,7 +45,7 @@ public class SignedMessageChain {
- SignedMessageLink signedMessageLink = SignedMessageChain.this.nextLink;
- if (signedMessageLink == null) {
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
-- } else if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
-+ } else if (me.earthme.luminol.config.modules.misc.InorderChatConfig.enabled && body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) { // Luminol - Add config for out-of-order chat checks
- this.setChainBroken();
- throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
- } else {
diff --git a/patches/server/0013-Add-config-for-tripwire-dupe.patch b/patches/server/0013-Add-config-for-tripwire-dupe.patch
deleted file mode 100644
index f888b05..0000000
--- a/patches/server/0013-Add-config-for-tripwire-dupe.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
-Date: Tue, 24 Dec 2024 13:28:56 -0500
-Subject: [PATCH] Add config for tripwire dupe
-
-Bring back MC-59471, MC-129055 on 1.21.2+, which fixed in 1.21.2 snapshots 24w33a and 24w36a
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..8def8aad908f5e6b828d7d9179bfe1962c39f9f7
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class TripwireConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "tripwire_dupe";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
-index c2589f42c467ca672417c24076313da51bb2dcbb..f85f53082cf5a56c723648f68bb103d58da0e8bd 100644
---- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
-+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
-@@ -206,7 +206,7 @@ public class TripWireHookBlock extends Block {
- if (iblockdata4 != null) {
- BlockState iblockdata5 = world.getBlockState(blockposition2);
-
-- if (iblockdata5.is(Blocks.TRIPWIRE) || iblockdata5.is(Blocks.TRIPWIRE_HOOK)) {
-+ if (me.earthme.luminol.config.modules.misc.TripwireConfig.enabled || iblockdata5.is(Blocks.TRIPWIRE) || iblockdata5.is(Blocks.TRIPWIRE_HOOK)) { // Luminol - Add config for tripwire dupe
- world.setBlock(blockposition2, (BlockState) iblockdata4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3);
- }
- }
diff --git a/patches/server/0014-Add-config-to-verify-signature-only-in-online-mode.patch b/patches/server/0014-Add-config-to-verify-signature-only-in-online-mode.patch
deleted file mode 100644
index ccd262f..0000000
--- a/patches/server/0014-Add-config-to-verify-signature-only-in-online-mode.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Stabrinai
-Date: Sun, 30 Jun 2024 20:46:42 +0800
-Subject: [PATCH] Add config to verify signature only in online-mode
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..e45ce3abf49684c911678abcefd69586246cc0e3
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/misc/PublickeyVerifyConfig.java
-@@ -0,0 +1,21 @@
-+package me.earthme.luminol.config.modules.misc;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class PublickeyVerifyConfig implements IConfigModule {
-+
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.MISC;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "verify_publickey_only_in_online_mode";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/player/ProfilePublicKey.java b/src/main/java/net/minecraft/world/entity/player/ProfilePublicKey.java
-index 6a7d7fad990fc44fdda6849d43dad141e61f7f37..dd470577fe314154b5a3677851eef95ebd151721 100644
---- a/src/main/java/net/minecraft/world/entity/player/ProfilePublicKey.java
-+++ b/src/main/java/net/minecraft/world/entity/player/ProfilePublicKey.java
-@@ -9,12 +9,15 @@ import java.time.Duration;
- import java.time.Instant;
- import java.util.Arrays;
- import java.util.UUID;
-+
-+import me.earthme.luminol.config.modules.misc.PublickeyVerifyConfig;
- import net.minecraft.network.FriendlyByteBuf;
- import net.minecraft.network.chat.Component;
- import net.minecraft.network.chat.ThrowingComponent;
- import net.minecraft.util.Crypt;
- import net.minecraft.util.ExtraCodecs;
- import net.minecraft.util.SignatureValidator;
-+import org.bukkit.Bukkit;
-
- public record ProfilePublicKey(ProfilePublicKey.Data data) {
- public static final Component EXPIRED_PROFILE_PUBLIC_KEY = Component.translatable("multiplayer.disconnect.expired_public_key");
-@@ -23,7 +26,7 @@ public record ProfilePublicKey(ProfilePublicKey.Data data) {
- public static final Codec TRUSTED_CODEC = ProfilePublicKey.Data.CODEC.xmap(ProfilePublicKey::new, ProfilePublicKey::data);
-
- public static ProfilePublicKey createValidated(SignatureValidator servicesSignatureVerifier, UUID playerUuid, ProfilePublicKey.Data publicKeyData) throws ProfilePublicKey.ValidationException {
-- if (!publicKeyData.validateSignature(servicesSignatureVerifier, playerUuid)) {
-+ if ((!PublickeyVerifyConfig.enabled || Bukkit.getServer().getOnlineMode()) && !publicKeyData.validateSignature(servicesSignatureVerifier, playerUuid)) { // Luminol - Verify signature only in online-mode
- throw new ProfilePublicKey.ValidationException(INVALID_SIGNATURE, org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PUBLIC_KEY_SIGNATURE); // Paper - kick event causes
- } else {
- return new ProfilePublicKey(publicKeyData);
diff --git a/patches/server/0018-Add-fix-for-off-region-adult-following-ai-behavior.patch b/patches/server/0018-Add-fix-for-off-region-adult-following-ai-behavior.patch
deleted file mode 100644
index 3c54a7a..0000000
--- a/patches/server/0018-Add-fix-for-off-region-adult-following-ai-behavior.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Fri, 6 Dec 2024 23:53:03 +0800
-Subject: [PATCH] Add fix for off region adult following ai behavior
-
-Might fix: https://github.com/PaperMC/Folia/issues/245
-
-diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
-index 0ff878a8cfcd6a3e08575b7537d9b7e2b817908f..742662da3497b0042fa0fb6ff3456fc62692473d 100644
---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java
-@@ -33,6 +33,13 @@ public class BabyFollowAdult {
- } else {
- LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type
-
-+ // Luminol start - Fix off world entity following which caused async issue
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entityageable1)) {
-+ memoryaccessor.erase();
-+ return true;
-+ }
-+ // Luminol end
-+
- if (entityageable.closerThan(entityageable1, (double) (executionRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) executionRange.getMinValue())) {
- // CraftBukkit start
- EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER);
diff --git a/patches/server/0021-Try-fixing-folia-spector-teleportation.patch b/patches/server/0021-Try-fixing-folia-spector-teleportation.patch
deleted file mode 100644
index b6f0e57..0000000
--- a/patches/server/0021-Try-fixing-folia-spector-teleportation.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 7 Feb 2024 06:30:03 +0000
-Subject: [PATCH] Try fixing folia spector teleportation
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..01f8c6ff3662569be5a4ff998bcd4fbbcb555105
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaSpectorTeleportationFixConfig.java
-@@ -0,0 +1,25 @@
-+package me.earthme.luminol.config.modules.fixes;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class FoliaSpectorTeleportationFixConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled", comments =
-+ """
-+ The teleportation of spector players would call absMoveTo directly.\s
-+ And when the camera teleported to another region,this would call absMoveTo\s
-+ to let the spector player move to another region without any checks, which \s
-+ would trigger the async catcher and crash the server""")
-+ public static boolean fixSpectorTeleportFolia = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.FIXES;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "folia.fix_spector_teleportation";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 93c038ba1fd216fd11ab8b5cec5807453f34e152..c72bda7413d9a7ce763743d0efbd85257262477e 100644
---- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
-+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -1162,9 +1162,24 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
- }
-
- Entity entity = this.getCamera();
-+ //Luminol start - Fix folia spector teleportation
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) && me.earthme.luminol.config.modules.fixes.FoliaSpectorTeleportationFixConfig.fixSpectorTeleportFolia){
-+ this.setCamera(this);
-+ }
-+ //Luminol end
-
- if (entity != this) {
-- if (entity.isAlive()) {
-+ // Luminol start - Fix folia spector teleportation
-+ var flag = false;
-+ var cameraPos = entity.blockPosition();
-+ var cameraLevel = entity.level();
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(cameraLevel, cameraPos) && me.earthme.luminol.config.modules.fixes.FoliaSpectorTeleportationFixConfig.fixSpectorTeleportFolia){
-+ this.setCamera(this);
-+ flag = true;
-+ }
-+ // Luminol end
-+
-+ if (entity.isAlive() && !flag) { // Luminol - Fix folia spector teleportation
- this.absMoveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
- this.serverLevel().getChunkSource().move(this);
- if (this.wantsToStopRiding()) {
diff --git a/patches/server/0023-Try-fixing-folia-off-region-POI-accessing-issue.patch b/patches/server/0023-Try-fixing-folia-off-region-POI-accessing-issue.patch
deleted file mode 100644
index 8ad99b3..0000000
--- a/patches/server/0023-Try-fixing-folia-off-region-POI-accessing-issue.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Mon, 10 Jun 2024 10:51:08 +0000
-Subject: [PATCH] Try fixing folia off region POI accessing issue
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..7812a71f05dd32646037afd22cdabf72bb23b0d1
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPOIAccessOffRegionFixConfig.java
-@@ -0,0 +1,25 @@
-+package me.earthme.luminol.config.modules.fixes;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class FoliaPOIAccessOffRegionFixConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled", comments =
-+ """
-+ The POIManager of folia has something which has not been patched\s
-+ for regionized ticking and these would trigger the async catcher\s
-+ and make the server crash.If you would like to prevent it and didn't\s
-+ mind the side effect(currently unknown), you can enable this""")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.FIXES;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "folia.fix_poi_access_off_region";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
-index aac1df9e2c0652bc6348af0404deba7465f82d42..ad812fd30d21ee3b7727105c66f2fc495a44f6ca 100644
---- a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java
-@@ -49,10 +49,17 @@ public class GoToPotentialJobSite extends Behavior {
- ServerLevel serverLevel2 = serverLevel.getServer().getLevel(pos.dimension());
- if (serverLevel2 != null) {
- PoiManager poiManager = serverLevel2.getPoiManager();
-+ //Luminol start - Fix off region POI accessing
-+ java.lang.Runnable scheduledRelease = () -> {
- if (poiManager.exists(blockPos, poiType -> true)) {
- poiManager.release(blockPos);
- }
--
-+ };
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(serverLevel2, blockPos) && me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled)
-+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(serverLevel2, blockPos.getX() >> 4, blockPos.getZ() >> 4, scheduledRelease);
-+ else
-+ scheduledRelease.run();
-+ //Luminol end
- DebugPackets.sendPoiTicketCountPacket(serverLevel, blockPos);
- }
- });
-diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/YieldJobSite.java b/src/main/java/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
-index d1a9b62d3304916275dd6b4c4e783cf1563b5e21..7d90e57b59ca1be1cc64ff6b53c64ea1f1767ad0 100644
---- a/src/main/java/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/YieldJobSite.java
-@@ -33,7 +33,10 @@ public class YieldJobSite {
- } else if (entity.getVillagerData().getProfession() != VillagerProfession.NONE) {
- return false;
- } else {
-- BlockPos blockPos = context.get(potentialJobSite).pos();
-+ final GlobalPos globalPos = context.get(potentialJobSite); //Luminol - Try fixing off main POI accessing
-+ final net.minecraft.server.level.ServerLevel targetLevel = net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension()); //Luminol - Try fixing off main POI accessing
-+ BlockPos blockPos = globalPos.pos(); //Luminol - Try fixing off main POI accessing
-+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(targetLevel, blockPos) && me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled) return true; //Luminol - Try fixing off main POI accessing
- Optional> optional = world.getPoiManager().getType(blockPos);
- if (optional.isEmpty()) {
- return true;
-diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
-index f3f98e6276dda3bc4f290fc2d80569f7e1e7ef66..edc127c94a54aed42120a5b4cc7036b5ddc8c656 100644
---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
-@@ -212,7 +212,7 @@ public class PoiManager extends SectionStorage im
-
- public Stream getInSquare(Predicate> typePredicate, BlockPos pos, int radius, PoiManager.Occupancy occupationStatus) {
- int i = Math.floorDiv(radius, 16) + 1;
-- return ChunkPos.rangeClosed(new ChunkPos(pos), i).flatMap(chunkPos -> this.getInChunk(typePredicate, chunkPos, occupationStatus)).filter(poi -> {
-+ return ChunkPos.rangeClosed(new ChunkPos(pos), i).filter(cpos -> me.earthme.luminol.config.modules.fixes.FoliaPOIAccessOffRegionFixConfig.enabled ? ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.world,cpos) : true).flatMap(chunkPos -> this.getInChunk(typePredicate, chunkPos, occupationStatus)).filter(poi -> { //Luminol - Fix off region POI access
- BlockPos blockPos2 = poi.getPos();
- return Math.abs(blockPos2.getX() - pos.getX()) <= radius && Math.abs(blockPos2.getZ() - pos.getZ()) <= radius;
- });
diff --git a/patches/server/0025-Force-disable-builtin-spark-plugin.patch b/patches/server/0025-Force-disable-builtin-spark-plugin.patch
deleted file mode 100644
index 5bc2fd1..0000000
--- a/patches/server/0025-Force-disable-builtin-spark-plugin.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:41:53 +0800
-Subject: [PATCH] Force disable builtin spark plugin
-
-
-diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
-index 48604e7f96adc9e226e034054c5e2bad0b024eb5..99f0c1e4d3437154a1062b0a8f94b7a04dd935af 100644
---- a/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
-+++ b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java
-@@ -88,7 +88,7 @@ public class FileProviderSource implements ProviderSource {
- }
-
- final PluginMeta config = type.getConfig(file);
-- if ((config.getName().equals("spark") && config.getMainClass().equals("me.lucko.spark.bukkit.BukkitSparkPlugin")) && !SparksFly.isPluginPreferred()) {
-+ if ((config.getName().equals("spark") && config.getMainClass().equals("me.lucko.spark.bukkit.BukkitSparkPlugin")) && !SparksFly.isPluginPreferred() && false) { // Luminol - Force disable builtin spark
- LOGGER.info("The spark plugin will not be loaded as this server bundles the spark profiler.");
- return;
- }
-diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 04f68856cb3d982f1644d26f5ae57587b6e36ff2..55bac6e6cccce6e0282936ac78bbe82628daa655 100644
---- a/src/main/java/net/minecraft/server/MinecraftServer.java
-+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -809,8 +809,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= j) {
-- this.server.spark.tickStart(); // Paper - spark
-+ if (false)this.server.spark.tickStart(); // Paper - spark // Luminol - Force disable builtin spark
- if (this.emptyTicks == j) {
- MinecraftServer.LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhileEmptySeconds());
- this.autoSave();
-@@ -1747,7 +1747,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop
-Date: Sat, 11 Jan 2025 18:41:11 +0800
-Subject: [PATCH] Merge Paper #11945 for temporary hooper behavior fix
-
-A hopper optimization fix on Paper's pr : https://github.com/PaperMC/Paper/pull/11945
-
-diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
-index 44aae845da6cd34fc00e0c71795d6f610679bd4b..df56451927d049c1baa5cd43ed0c25a3837474ec 100644
---- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
-+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
-@@ -764,8 +764,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
- } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
- int j = Math.min(stack.getMaxStackSize(), to.getMaxStackSize()) - itemstack1.getCount(); // Paper - Make hoppers respect inventory max stack size
- int k = Math.min(stack.getCount(), j);
--
-- stack.shrink(k);
-+ stack = stack.copy(true); // Paper - Perf: Optimize Hoppers
-+ stack.shrink(k); // Paper - Perf: Optimize Hoppers
- itemstack1.grow(k);
- flag = k > 0;
- }
diff --git a/patches/server/0028-Kaiiju-Don-t-pathfind-outside-region.patch b/patches/server/0028-Kaiiju-Don-t-pathfind-outside-region.patch
deleted file mode 100644
index 76635a2..0000000
--- a/patches/server/0028-Kaiiju-Don-t-pathfind-outside-region.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: M2ke4U <79621885+MrHua269@users.noreply.github.com>
-Date: Sat, 25 Nov 2023 19:03:34 +0800
-Subject: [PATCH] Kaiiju Don't pathfind outside region
-
-
-diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
-index 2a7a26ca447cc78f24e61a2bf557411c31eb16b2..361e79e13dacc765283b2736324f365400e9860e 100644
---- a/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
-@@ -120,7 +120,9 @@ public class MoveToTargetSink extends Behavior {
-
- private boolean tryComputePath(Mob entity, WalkTarget walkTarget, long time) {
- BlockPos blockPos = walkTarget.getTarget().currentBlockPosition();
-+ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((ServerLevel) entity.level(), blockPos)) // Kaiiju - Don't pathfind outside region
- this.path = entity.getNavigation().createPath(blockPos, 0);
-+ else this.path = null; // Kaiiju - Don't pathfind outside region
- this.speedModifier = walkTarget.getSpeedModifier();
- Brain> brain = entity.getBrain();
- if (this.reachedTarget(entity, walkTarget)) {
diff --git a/patches/server/0032-Pufferfish-Cache-climbing-check-for-activation.patch b/patches/server/0032-Pufferfish-Cache-climbing-check-for-activation.patch
deleted file mode 100644
index f66bcf6..0000000
--- a/patches/server/0032-Pufferfish-Cache-climbing-check-for-activation.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:52:43 +0800
-Subject: [PATCH] Pufferfish Cache climbing check for activation
-
-
-diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index 73af15d18180b4df3fa0614b323f2397f5543db5..dcdc5ca699832b3c26b33a27f684a4c7dea103b9 100644
---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
-+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-@@ -2154,6 +2154,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
- return this.lastClimbablePos;
- }
-
-+
-+ // Pufferfish start
-+ private boolean cachedOnClimable = false;
-+ private BlockPos lastClimbingPosition = null;
-+
-+ public boolean onClimableCached() {
-+ if (!this.blockPosition().equals(this.lastClimbingPosition)) {
-+ this.cachedOnClimable = this.onClimbable();
-+ this.lastClimbingPosition = this.blockPosition();
-+ }
-+ return this.cachedOnClimable;
-+ }
-+ // Pufferfish end
-+
- public boolean onClimbable() {
- if (this.isSpectator()) {
- return false;
-diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
-index f2f5eb1a443ac411539e1c87eec60e76682b82fa..cbe785f5fab22630e8a80519664791e2ac621b9f 100644
---- a/src/main/java/org/spigotmc/ActivationRange.java
-+++ b/src/main/java/org/spigotmc/ActivationRange.java
-@@ -304,7 +304,7 @@ public class ActivationRange
- if ( entity instanceof LivingEntity )
- {
- LivingEntity living = (LivingEntity) entity;
-- if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing()) // Paper
-+ if ( living.onClimableCached() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing() ) // Paper // Pufferfish - use cached
- {
- return 1; // Paper
- }
diff --git a/patches/server/0033-Pufferfish-Reduce-chunk-loading-lookups.patch b/patches/server/0033-Pufferfish-Reduce-chunk-loading-lookups.patch
deleted file mode 100644
index 514eebd..0000000
--- a/patches/server/0033-Pufferfish-Reduce-chunk-loading-lookups.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:53:29 +0800
-Subject: [PATCH] Pufferfish Reduce chunk loading & lookups
-
-
-diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
-index 2a394381a4ad46359359ba402b65c62b331480b4..4e4dab5bc202f6f421dcff98f0e36e8e70378b49 100644
---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
-+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
-@@ -306,11 +306,17 @@ public class EnderMan extends Monster implements NeutralMob {
- private boolean teleport(double x, double y, double z) {
- BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, y, z);
-
-- while (blockposition_mutableblockposition.getY() > this.level().getMinY() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) {
-+ // Pufferfish start - single chunk lookup
-+ net.minecraft.world.level.chunk.LevelChunk chunk = this.level().getChunkIfLoaded(blockposition_mutableblockposition);
-+ if (chunk == null) {
-+ return false;
-+ }
-+ // Pufferfish end
-+ while (blockposition_mutableblockposition.getY() > this.level().getMinY() && !chunk.getBlockState(blockposition_mutableblockposition).blocksMotion()) { // Pufferfish
- blockposition_mutableblockposition.move(Direction.DOWN);
- }
-
-- BlockState iblockdata = this.level().getBlockState(blockposition_mutableblockposition);
-+ BlockState iblockdata = chunk.getBlockState(blockposition_mutableblockposition); // Pufferfish
- boolean flag = iblockdata.blocksMotion();
- boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER);
-
diff --git a/patches/server/0034-Pufferfish-Fix-Paper-6045-block-goal-shouldn-t-load-.patch b/patches/server/0034-Pufferfish-Fix-Paper-6045-block-goal-shouldn-t-load-.patch
deleted file mode 100644
index 9084c67..0000000
--- a/patches/server/0034-Pufferfish-Fix-Paper-6045-block-goal-shouldn-t-load-.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:54:17 +0800
-Subject: [PATCH] Pufferfish Fix Paper#6045, block goal shouldn't load chunks
-
-
-diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
-index aee0147649d458b87d92496eda0c1723ebe570d2..89e9ea999d2fbd81a1d74382ef3fcd675fc8b94e 100644
---- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
-@@ -121,6 +121,7 @@ public abstract class MoveToBlockGoal extends Goal {
- for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
- for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
- mutableBlockPos.setWithOffset(blockPos, m, k - 1, n);
-+ if (!this.mob.level().hasChunkAt(mutableBlockPos)) continue; // Pufferfish - if this block isn't loaded, continue
- if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) {
- this.blockPos = mutableBlockPos;
- this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper
diff --git a/patches/server/0035-Pufferfish-Reduce-projectile-chunk-loading.patch b/patches/server/0035-Pufferfish-Reduce-projectile-chunk-loading.patch
deleted file mode 100644
index 4246ad4..0000000
--- a/patches/server/0035-Pufferfish-Reduce-projectile-chunk-loading.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:54:58 +0800
-Subject: [PATCH] Pufferfish Reduce projectile chunk loading
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..12683ec5a5102e45b6171fea0b833ba57e5e188c
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/ProjectileChunkReduceConfig.java
-@@ -0,0 +1,22 @@
-+package me.earthme.luminol.config.modules.optimizations;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class ProjectileChunkReduceConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "max-loads-per-tick")
-+ public static int maxProjectileLoadsPerTick;
-+ @ConfigInfo(baseName = "max-loads-per-projectile")
-+ public static int maxProjectileLoadsPerProjectile;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.OPTIMIZATIONS;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "projectile";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-index a6bcf7b57b804af74f75c0b24ff48ee2714c3b73..7ccd7d6dc61948210ecb9c3acee8f1740e389106 100644
---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-@@ -58,6 +58,40 @@ public abstract class Projectile extends Entity implements TraceableEntity {
- super(type, world);
- }
-
-+ // Pufferfish start
-+ private static final java.lang.ThreadLocal loadedThisTick = java.lang.ThreadLocal.withInitial(() -> 0L);
-+ private static final java.lang.ThreadLocal loadedTick = java.lang.ThreadLocal.withInitial(() -> 0L);
-+
-+ private int loadedLifetime = 0;
-+ @Override
-+ public void setPos(double x, double y, double z) {
-+ if (io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion() != null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this)){
-+ long currentTick = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getData().getCurrentTick();
-+
-+ if (loadedTick.get() != currentTick) {
-+ loadedTick.set(currentTick);
-+ loadedThisTick.set(0L);
-+ }
-+
-+ int previousX = Mth.floor(this.getX()) >> 4, previousZ = Mth.floor(this.getZ()) >> 4;
-+ int newX = Mth.floor(x) >> 4, newZ = Mth.floor(z) >> 4;
-+ if ((previousX != newX || previousZ != newZ) && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level(), newX, newZ)) {
-+ boolean isLoaded = ((net.minecraft.server.level.ServerChunkCache) this.level().getChunkSource()).getChunkAtIfCachedImmediately(newX, newZ) != null;
-+ if (!isLoaded) {
-+ if (Projectile.loadedThisTick.get() > me.earthme.luminol.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerTick) {
-+ if (++this.loadedLifetime > me.earthme.luminol.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerProjectile) {
-+ this.discard();
-+ }
-+ return;
-+ }
-+ Projectile.loadedThisTick.set(Projectile.loadedThisTick.get() + 1);
-+ }
-+ }
-+ }
-+ super.setPos(x, y, z);
-+ }
-+ // Pufferfish end
-+
- public void setOwner(@Nullable Entity entity) {
- if (entity != null) {
- this.ownerUUID = entity.getUUID();
diff --git a/patches/server/0036-Pufferfish-Only-check-for-spooky-season-once-an-hour.patch b/patches/server/0036-Pufferfish-Only-check-for-spooky-season-once-an-hour.patch
deleted file mode 100644
index f395a0a..0000000
--- a/patches/server/0036-Pufferfish-Only-check-for-spooky-season-once-an-hour.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 11:59:05 +0800
-Subject: [PATCH] Pufferfish Only check for spooky season once an hour
-
-
-diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-index 60c2868f255d372226e0c1389caaa5477bbef41e..4f2993214f1789251742fe106bc7acad5b37440b 100644
---- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-@@ -242,13 +242,25 @@ public class Bat extends AmbientCreature {
- }
- }
-
-+ // Pufferfish start - only check for spooky season once an hour
-+ private static boolean isSpookySeason = false;
-+ private static final int ONE_HOUR = 20 * 60 * 60;
-+ private static int lastSpookyCheck = -ONE_HOUR;
- private static boolean isHalloween() {
-+ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion region =
-+ io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion();
-+ final long tickCount = region.getData().getCurrentTick();
-+ if (tickCount - lastSpookyCheck > ONE_HOUR) {
- LocalDate localdate = LocalDate.now();
- int i = localdate.get(ChronoField.DAY_OF_MONTH);
- int j = localdate.get(ChronoField.MONTH_OF_YEAR);
-
-- return j == 10 && i >= 20 || j == 11 && i <= 3;
-+ isSpookySeason = j == 10 && i >= 20 || j == 11 && i <= 3;
-+ lastSpookyCheck = (int) tickCount;
-+ }
-+ return isSpookySeason;
- }
-+ // Pufferfish end
-
- private void setupAnimationStates() {
- if (this.isResting()) {
diff --git a/patches/server/0037-Pufferfish-Optimize-suffocation.patch b/patches/server/0037-Pufferfish-Optimize-suffocation.patch
deleted file mode 100644
index 7d710e5..0000000
--- a/patches/server/0037-Pufferfish-Optimize-suffocation.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Sat, 30 Nov 2024 12:05:17 +0800
-Subject: [PATCH] Pufferfish Optimize suffocation
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..3e48cd297b4869e5c89b6abc43c726d3a7511e7f
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/SuffocationOptimizationConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.optimizations;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class SuffocationOptimizationConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.OPTIMIZATIONS;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "suffocation_optimization";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index dcdc5ca699832b3c26b33a27f684a4c7dea103b9..f537fd0a6bf689b5804924950d1b7acf51664f33 100644
---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
-+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-@@ -480,7 +480,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
-
- if (world1 instanceof ServerLevel) {
- worldserver1 = (ServerLevel) world1;
-- if (this.isInWall()) {
-+ if (shouldCheckForSuffocation() && this.isInWall()) { // Pufferfish - optimize suffocation
- this.hurtServer(worldserver1, this.damageSources().inWall(), 1.0F);
- } else if (flag && !this.level().getWorldBorder().isWithinBounds(this.getBoundingBox())) {
- double d1 = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone();
-@@ -1456,6 +1456,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
- return this.getHealth() <= 0.0F;
- }
-
-+ // Pufferfish start - optimize suffocation
-+ public boolean couldPossiblyBeHurt(float amount) {
-+ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && amount <= this.lastHurt) {
-+ return false;
-+ }
-+ return true;
-+ }
-+
-+ public boolean shouldCheckForSuffocation() {
-+ return !me.earthme.luminol.config.modules.optimizations.SuffocationOptimizationConfig.enabled || (tickCount % 10 == 0 && couldPossiblyBeHurt(1.0F));
-+ }
-+ // Pufferfish end
-+
- @Override
- public boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
- if (this.isInvulnerableTo(world, source)) {
-diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
-index bd9e10f79eaf0d23908229b3ebc2227946a14843..2ce65ef77e4b28e1fd5ac7bd6a304cc115b8aca2 100644
---- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
-+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
-@@ -151,6 +151,13 @@ public class WitherBoss extends Monster implements RangedAttackMob {
- this.bossEvent.setName(this.getDisplayName());
- }
-
-+ // Pufferfish start - optimize suffocation
-+ @Override
-+ public boolean shouldCheckForSuffocation() {
-+ return true;
-+ }
-+ // Pufferfish end
-+
- @Override
- protected SoundEvent getAmbientSound() {
- return SoundEvents.WITHER_AMBIENT;
diff --git a/patches/server/0038-Pufferfish-Dynamic-Activation-of-Brain.patch b/patches/server/0038-Pufferfish-Dynamic-Activation-of-Brain.patch
deleted file mode 100644
index b164b4c..0000000
--- a/patches/server/0038-Pufferfish-Dynamic-Activation-of-Brain.patch
+++ /dev/null
@@ -1,384 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 4 Dec 2024 23:49:02 +0800
-Subject: [PATCH] Pufferfish Dynamic Activation of Brain
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityDABConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityDABConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..af5893ba1f738ec9827d7b714682c314229292d9
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityDABConfig.java
-@@ -0,0 +1,60 @@
-+package me.earthme.luminol.config.modules.optimizations;
-+
-+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.DoNotLoad;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+import net.minecraft.core.registries.BuiltInRegistries;
-+import net.minecraft.server.MinecraftServer;
-+import net.minecraft.world.entity.EntityType;
-+import java.util.Collections;
-+import java.util.List;
-+
-+public class EntityDABConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean dearEnabled = false;
-+ @ConfigInfo(baseName = "start_distance",comments =
-+ "This value determines how far away an entity has to be\n" +
-+ " from the player to start being effected by DEAR."
-+ )
-+ public static int startDistance = 12;
-+ @DoNotLoad
-+ public static int startDistanceSquared;
-+ @ConfigInfo(baseName = "max-tick-freq",comments =
-+ "This value defines how often in ticks, the furthest entity\n"+
-+ "will get their pathfinders and behaviors ticked. 20 = 1s")
-+ public static int maximumActivationPrio = 20;
-+ @ConfigInfo(baseName = "activation-dist-mod",comments =
-+ """
-+ This value defines how much distance modifies an entity's
-+ tick frequency. freq = (distanceToPlayer^2) / (2^value)
-+ If you want further away entities to tick less often, use 7.
-+ If you want further away entities to tick more often, try 9.""")
-+ public static int activationDistanceMod;
-+ @ConfigInfo(baseName = "blacklisted-entities")
-+ public static List blackedEntities = Collections.emptyList();
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.OPTIMIZATIONS;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "dab";
-+ }
-+
-+ @Override
-+ public void onLoaded(CommentedFileConfig config) {
-+ for (EntityType> entityType : BuiltInRegistries.ENTITY_TYPE) {
-+ entityType.dabEnabled = true; // reset all, before setting the ones to true
-+ }
-+
-+ blackedEntities.forEach(name -> EntityType.byString(name).ifPresentOrElse(entityType -> {
-+ entityType.dabEnabled = false;
-+ }, () -> MinecraftServer.LOGGER.warn("Unknown entity \"" + name + "\"")));
-+
-+ config.setComment("optimizations.dab", "Optimizes entity brains when\n" + "they're far away from the player");
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 5503d506c595296ecad09a3ce4497a365f216af5..98aef7a3cfc759e4415df3a56b5fe01eb50b0428 100644
---- a/src/main/java/net/minecraft/server/level/ServerLevel.java
-+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -816,6 +816,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
- } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); } // Folia - profiler
- profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); try { // Folia - profiler
- regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking
-+ entity.activatedPriorityReset = false; // Pufferfish - DAB
- if (!entity.isRemoved()) {
- if (!tickratemanager.isEntityFrozen(entity)) {
- gameprofilerfiller.push("checkDespawn");
-diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 64e081f993c2c844f83af227380b8a957eaabad4..15cbbd8c660b8544bd39c8f4ebe8e44922fe81b1 100644
---- a/src/main/java/net/minecraft/world/entity/Entity.java
-+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -390,6 +390,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
- public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
- public boolean fixedPose = false; // Paper - Expand Pose API
- private final int despawnTime; // Paper - entity despawn time limit
-+ public boolean activatedPriorityReset = false; // Pufferfish - DAB
-+ public int activatedPriority = me.earthme.luminol.config.modules.optimizations.EntityDABConfig.maximumActivationPrio; // Pufferfish - DAB (golf score)
-
- public void setOrigin(@javax.annotation.Nonnull Location location) {
- this.origin = location.toVector();
-diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
-index 635c9c7a8c8307c2bc845a8e1f24aacb526a3c92..c824e8a540dccffd848ae0a0624ce034b78f7db6 100644
---- a/src/main/java/net/minecraft/world/entity/EntityType.java
-+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
-@@ -385,6 +385,7 @@ public class EntityType implements FeatureElement, EntityTypeT
- private final int clientTrackingRange;
- private final int updateInterval;
- private final String descriptionId;
-+ public boolean dabEnabled = false; // Pufferfish
- @Nullable
- private Component description;
- private final Optional> lootTable;
-diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
-index 6b66d73daa0145829cd964403e7958335ef0aa9a..80756e96faed0e0ca239f58f63522b9f15822c07 100644
---- a/src/main/java/net/minecraft/world/entity/Mob.java
-+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -235,10 +235,10 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
- @Override
- public void inactiveTick() {
- super.inactiveTick();
-- if (this.goalSelector.inactiveTick()) {
-+ if (this.goalSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priroity
- this.goalSelector.tick();
- }
-- if (this.targetSelector.inactiveTick()) {
-+ if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priority
- this.targetSelector.tick();
- }
- }
-@@ -939,16 +939,20 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
-
- if (i % 2 != 0 && this.tickCount > 1) {
- gameprofilerfiller.push("targetSelector");
-+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.targetSelector.tickRunningGoals(false);
- gameprofilerfiller.pop();
- gameprofilerfiller.push("goalSelector");
-+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.goalSelector.tickRunningGoals(false);
- gameprofilerfiller.pop();
- } else {
- gameprofilerfiller.push("targetSelector");
-+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.targetSelector.tick();
- gameprofilerfiller.pop();
- gameprofilerfiller.push("goalSelector");
-+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
- this.goalSelector.tick();
- gameprofilerfiller.pop();
- }
-diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
-index 29ae74339a4831ccef3d01e8054931715ba192ad..dd08eb5d44de5a482df538bca18a2255bb93a81f 100644
---- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
-+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
-@@ -38,9 +38,12 @@ public class GoalSelector {
- }
-
- // Paper start - EAR 2
-- public boolean inactiveTick() {
-+ public boolean inactiveTick(int tickRate, boolean inactive) { // Pufferfish start
-+ if (inactive && !me.earthme.luminol.config.modules.optimizations.EntityDABConfig.dearEnabled) tickRate = 4; // reset to Paper's
-+ tickRate = Math.min(tickRate, 3);
- this.curRate++;
-- return this.curRate % 3 == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct
-+ return this.curRate % tickRate == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct
-+ // Pufferfish end
- }
- public boolean hasTasks() {
- for (WrappedGoal task : this.availableGoals) {
-diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
-index b86f638390d386c838318a4d9b6571ac5514df8f..f4788104b1bb73810fdf0dc7f5311d5b078a81d5 100644
---- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
-+++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
-@@ -223,11 +223,13 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
- return 0.4F;
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("allayBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- gameprofilerfiller.push("allayActivityUpdate");
-diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
-index 31b10cd404b672d7ce21c2107d8f83e32de26ef4..cb47876a13cb1990bb0ab4cff1bbe57b3b2d0a5e 100644
---- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
-+++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
-@@ -292,11 +292,13 @@ public class Axolotl extends Animal implements VariantHolder, B
- return true;
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("axolotlBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- gameprofilerfiller.push("axolotlActivityUpdate");
-diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
-index ca04e5d829331551a2c2f44e223ff05c6ce04e76..db91b8018591fe248efda417fcde7fd2071c4cb6 100644
---- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
-+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java
-@@ -184,10 +184,12 @@ public class Frog extends Animal implements VariantHolder> {
- .ifPresent(this::setVariant);
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller profilerFiller = Profiler.get();
- profilerFiller.push("frogBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- profilerFiller.pop();
- profilerFiller.push("frogActivityUpdate");
-diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
-index 48ac8c3f6e00c3c2dc67b6c994be7c0ac6dfcf81..cf326ef35bac732e7addf75537963593d5b268ae 100644
---- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
-+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
-@@ -83,11 +83,13 @@ public class Tadpole extends AbstractFish {
- return SoundEvents.TADPOLE_FLOP;
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("tadpoleBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- gameprofilerfiller.push("tadpoleActivityUpdate");
-diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
-index 76aca47d8638d5c37c57d3a59fa7f8ceaa5a53b4..fb92cd4b0c15b614c0c06d2867039aee1a6212a2 100644
---- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
-+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
-@@ -192,11 +192,13 @@ public class Goat extends Animal {
- return (Brain) super.getBrain(); // CraftBukkit - decompile error
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("goatBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- gameprofilerfiller.push("goatActivityUpdate");
-diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
-index 92270912ef26924f611a1df7cb3d5b485b0a262d..9c20651b74157582e60793ceba8adde2c354f2a8 100644
---- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
-+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
-@@ -138,11 +138,13 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
- return (Brain) super.getBrain(); // CraftBukkit - decompile error
- }
-
-+ private int behaviorTick; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("hoglinBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- HoglinAi.updateActivity(this);
-diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
-index 2121d2a2e1aa1d0f0390cc515317096431f6dcb0..74ab50723056fef2a96dcc9e2de0e58526738011 100644
---- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
-+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
-@@ -307,11 +307,13 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
- return !this.cannotHunt;
- }
-
-+ private int behaviorTick; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("piglinBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- PiglinAi.updateActivity(this);
-diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
-index c47ed605f0822effd58df4f875297ed015e1e57e..4331ada8bed7ade7b53fd8ba000c1c1b34fa4331 100644
---- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
-+++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
-@@ -275,11 +275,13 @@ public class Warden extends Monster implements VibrationSystem {
-
- }
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("wardenBrain");
-+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish
- this.getBrain().tick(world, this);
- gameprofilerfiller.pop();
- super.customServerAiStep(world);
-diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
-index 07f50048e9748b28178847ad470b8b2ce37e0eea..8fbf0df15716940622144fb2d4423f74264580f7 100644
---- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
-+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
-@@ -142,6 +142,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
- return holder.is(PoiTypes.MEETING);
- });
-
-+ public long nextGolemPanic = -1; // Pufferfish
-+
- public Villager(EntityType extends Villager> entityType, Level world) {
- this(entityType, world, VillagerType.PLAINS);
- }
-@@ -245,6 +247,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
- }
- // Spigot End
-
-+ private int behaviorTick = 0; // Pufferfish
- @Override
- protected void customServerAiStep(ServerLevel world) {
- // Paper start - EAR 2
-@@ -255,7 +258,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("villagerBrain");
-- if (!inactive) this.getBrain().tick(world, this);
-+ // Pufferfish start
-+ if (!inactive && this.behaviorTick++ % this.activatedPriority == 0) {
-+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper
-+ }
-+ // Pufferfish end
- gameprofilerfiller.pop();
- if (this.assignProfessionWhenSpawned) {
- this.assignProfessionWhenSpawned = false;
-diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
-index cbe785f5fab22630e8a80519664791e2ac621b9f..820145408fa2150820c4c14ea55bee23e7e9a366 100644
---- a/src/main/java/org/spigotmc/ActivationRange.java
-+++ b/src/main/java/org/spigotmc/ActivationRange.java
-@@ -37,6 +37,10 @@ import net.minecraft.world.entity.projectile.ThrownTrident;
- import net.minecraft.world.entity.raid.Raider;
- import net.minecraft.world.level.Level;
- import net.minecraft.world.phys.AABB;
-+// Pufferfish start
-+import net.minecraft.world.phys.Vec3;
-+import java.util.List;
-+// Pufferfish end
-
- public class ActivationRange
- {
-@@ -230,6 +234,25 @@ public class ActivationRange
- }
- // Paper end - Configurable marker ticking
- ActivationRange.activateEntity(entity, bbByType); // Folia - threaded regions
-+
-+ // Pufferfish start
-+ if (me.earthme.luminol.config.modules.optimizations.EntityDABConfig.dearEnabled && entity.getType().dabEnabled) {
-+ if (!entity.activatedPriorityReset) {
-+ entity.activatedPriorityReset = true;
-+ entity.activatedPriority = me.earthme.luminol.config.modules.optimizations.EntityDABConfig.maximumActivationPrio;
-+ }
-+ Vec3 playerVec = player.position();
-+ Vec3 entityVec = entity.position();
-+ double diffX = playerVec.x - entityVec.x, diffY = playerVec.y - entityVec.y, diffZ = playerVec.z - entityVec.z;
-+ int squaredDistance = (int) (diffX * diffX + diffY * diffY + diffZ * diffZ);
-+ entity.activatedPriority = squaredDistance > me.earthme.luminol.config.modules.optimizations.EntityDABConfig.startDistanceSquared ?
-+ Math.max(1, Math.min(squaredDistance >> me.earthme.luminol.config.modules.optimizations.EntityDABConfig.activationDistanceMod, entity.activatedPriority)) :
-+ 1;
-+ } else {
-+ entity.activatedPriority = 1;
-+ }
-+ // Pufferfish end
-+
- }
- // Paper end
- }
diff --git a/patches/server/0039-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch b/patches/server/0039-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch
deleted file mode 100644
index 1b88cc5..0000000
--- a/patches/server/0039-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 4 Dec 2024 23:50:22 +0800
-Subject: [PATCH] Pufferfish Throttle goal selector during inactive ticking
-
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..acc032f727e605e79b688efb4873ff474fe7e132
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/EntityGoalSelectorInactiveTickConfig.java
-@@ -0,0 +1,20 @@
-+package me.earthme.luminol.config.modules.optimizations;
-+
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+
-+public class EntityGoalSelectorInactiveTickConfig implements IConfigModule {
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = false;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.OPTIMIZATIONS;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "skip_goal_selector_tick_in_inactive_tick";
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
-index 80756e96faed0e0ca239f58f63522b9f15822c07..4e587a5c59eb271ed31c5584bd665953ae82aa8a 100644
---- a/src/main/java/net/minecraft/world/entity/Mob.java
-+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -231,11 +231,13 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
- return this.lookControl;
- }
-
-+ int _pufferfish_inactiveTickDisableCounter = 0; // Pufferfish - throttle inactive goal selector ticking
- // Paper start
- @Override
- public void inactiveTick() {
- super.inactiveTick();
-- if (this.goalSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priroity
-+ boolean isThrottled = me.earthme.luminol.config.modules.optimizations.EntityGoalSelectorInactiveTickConfig.enabled && _pufferfish_inactiveTickDisableCounter++ % 20 != 0; // Pufferfish - throttle inactive goal selector ticking
-+ if (this.goalSelector.inactiveTick(this.activatedPriority, true) && !isThrottled) { // Pufferfish - pass activated priroity // Pufferfish - throttle inactive goal selector ticking
- this.goalSelector.tick();
- }
- if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priority
diff --git a/patches/server/0040-Pufferfish-SIMD-Utilities.patch b/patches/server/0040-Pufferfish-SIMD-Utilities.patch
deleted file mode 100644
index 759a719..0000000
--- a/patches/server/0040-Pufferfish-SIMD-Utilities.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrHua269
-Date: Wed, 4 Dec 2024 23:51:17 +0800
-Subject: [PATCH] Pufferfish SIMD Utilities
-
-
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 4b79f96103c98896332113ffe5f0e22cf08ffdd1..fbf51f738e98ac6e8358a7fa81b7fc545469a5a6 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -94,6 +94,14 @@ paperweight {
- craftBukkitPackageVersion.set("v1_21_R3") // also needs to be updated in MappingEnvironment
- }
-
-+
-+// Pufferfish Start
-+tasks.withType {
-+ val compilerArgs = options.compilerArgs
-+ compilerArgs.add("--add-modules=jdk.incubator.vector")
-+}
-+// Pufferfish End
-+
- tasks.jar {
- archiveClassifier.set("dev")
-
-diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..76cea165bcef0794a66ef7c29721f7716869420f
---- /dev/null
-+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java
-@@ -0,0 +1,53 @@
-+package me.earthme.luminol.config.modules.optimizations;
-+
-+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
-+import com.mojang.logging.LogUtils;
-+import gg.pufferfish.pufferfish.simd.SIMDDetection;
-+import me.earthme.luminol.config.ConfigInfo;
-+import me.earthme.luminol.config.DoNotLoad;
-+import me.earthme.luminol.config.EnumConfigCategory;
-+import me.earthme.luminol.config.IConfigModule;
-+import org.slf4j.Logger;
-+
-+public class SIMDConfig implements IConfigModule {
-+ @DoNotLoad
-+ private static final Logger LOGGER = LogUtils.getLogger();
-+ @ConfigInfo(baseName = "enabled")
-+ public static boolean enabled = true;
-+
-+ @Override
-+ public EnumConfigCategory getCategory() {
-+ return EnumConfigCategory.OPTIMIZATIONS;
-+ }
-+
-+ @Override
-+ public String getBaseName() {
-+ return "use_simd";
-+ }
-+
-+ @Override
-+ public void onLoaded(CommentedFileConfig configInstance) {
-+ if (!enabled){
-+ return;
-+ }
-+
-+ // Attempt to detect vectorization
-+ try {
-+ SIMDDetection.isEnabled = SIMDDetection.canEnable(LOGGER);
-+ SIMDDetection.versionLimited = SIMDDetection.getJavaVersion() < 17;
-+ } catch (NoClassDefFoundError | Exception ignored) {
-+ ignored.printStackTrace();
-+ }
-+
-+ if (SIMDDetection.isEnabled) {
-+ LOGGER.info("SIMD operations detected as functional. Will replace some operations with faster versions.");
-+ } else if (SIMDDetection.versionLimited) {
-+ LOGGER.warn("Will not enable SIMD! These optimizations are only safely supported on Java 17+.");
-+ } else {
-+ LOGGER.warn("SIMD operations are available for your server, but are not configured!");
-+ LOGGER.warn("To enable additional optimizations, add \"--add-modules=jdk.incubator.vector\" to your startup flags, BEFORE the \"-jar\".");
-+ LOGGER.warn("If you have already added this flag, then SIMD operations are not supported on your JVM or CPU.");
-+ LOGGER.warn("Debug: Java: {}, test run: {}", System.getProperty("java.version"), SIMDDetection.testRun);
-+ }
-+ }
-+}
diff --git a/patches/server/0041-Pufferfish-Sentry.patch b/patches/server/0041-Pufferfish-Sentry.patch
deleted file mode 100644
index d3cef4e..0000000
--- a/patches/server/0041-Pufferfish-Sentry.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: adabugra <57899270+adabugra@users.noreply.github.com>
-Date: Mon, 6 Jan 2025 19:24:05 +0300
-Subject: [PATCH] Pufferfish: Sentry
-
-
-diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..2b830cb288ceba390ed39cd33fc1ee855357a97e
---- /dev/null
-+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java
-@@ -0,0 +1,133 @@
-+package gg.pufferfish.pufferfish.sentry;
-+
-+import com.google.common.reflect.TypeToken;
-+import com.google.gson.Gson;
-+import io.sentry.Breadcrumb;
-+import io.sentry.Sentry;
-+import io.sentry.SentryEvent;
-+import io.sentry.SentryLevel;
-+import io.sentry.protocol.Message;
-+import io.sentry.protocol.User;
-+
-+import java.util.Map;
-+
-+import me.earthme.luminol.config.modules.misc.SentryConfig;
-+import org.apache.logging.log4j.Level;
-+import org.apache.logging.log4j.LogManager;
-+import org.apache.logging.log4j.Marker;
-+import org.apache.logging.log4j.core.LogEvent;
-+import org.apache.logging.log4j.core.Logger;
-+import org.apache.logging.log4j.core.appender.AbstractAppender;
-+import org.apache.logging.log4j.core.filter.AbstractFilter;
-+
-+public class PufferfishSentryAppender extends AbstractAppender {
-+
-+ private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(PufferfishSentryAppender.class.getSimpleName());
-+ private static final Gson GSON = new Gson();
-+ private final Level logLevel;
-+
-+ public PufferfishSentryAppender(Level logLevel) {
-+ super("PufferfishSentryAdapter", new SentryFilter(), null);
-+ this.logLevel = logLevel;
-+ }
-+
-+ @Override
-+ public void append(LogEvent logEvent) {
-+ if (logEvent.getLevel().isMoreSpecificThan(logLevel) && (logEvent.getThrown() != null || !SentryConfig.onlyLogThrown)) {
-+ try {
-+ logException(logEvent);
-+ } catch (Exception e) {
-+ logger.warn("Failed to log event with sentry", e);
-+ }
-+ } else {
-+ try {
-+ logBreadcrumb(logEvent);
-+ } catch (Exception e) {
-+ logger.warn("Failed to log event with sentry", e);
-+ }
-+ }
-+ }
-+
-+ private void logException(LogEvent e) {
-+ SentryEvent event = new SentryEvent(e.getThrown());
-+
-+ Message sentryMessage = new Message();
-+ sentryMessage.setMessage(e.getMessage().getFormattedMessage());
-+
-+ event.setThrowable(e.getThrown());
-+ event.setLevel(getLevel(e.getLevel()));
-+ event.setLogger(e.getLoggerName());
-+ event.setTransaction(e.getLoggerName());
-+ event.setExtra("thread_name", e.getThreadName());
-+
-+ boolean hasContext = e.getContextData() != null;
-+
-+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_playerid")) {
-+ User user = new User();
-+ user.setId(e.getContextData().getValue("pufferfishsentry_playerid"));
-+ user.setUsername(e.getContextData().getValue("pufferfishsentry_playername"));
-+ event.setUser(user);
-+ }
-+
-+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_pluginname")) {
-+ event.setExtra("plugin.name", e.getContextData().getValue("pufferfishsentry_pluginname"));
-+ event.setExtra("plugin.version", e.getContextData().getValue("pufferfishsentry_pluginversion"));
-+ event.setTransaction(e.getContextData().getValue("pufferfishsentry_pluginname"));
-+ }
-+
-+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_eventdata")) {
-+ Map eventFields = GSON.fromJson((String) e.getContextData().getValue("pufferfishsentry_eventdata"), new TypeToken