Compare commits

..

31 Commits

Author SHA1 Message Date
Kercute
08cc27a648 Updated Upstream (Folia) 2025-03-08 23:09:59 +08:00
MrHua269
531d824a55 [ci skip] Use --global flag to configure git 2025-03-08 20:11:22 +08:00
MrHua269
0f6e3ac870 Add experiment config for entity to clean memory value which is not belong to current tickregion & Fix a series issue around entity memory typed GlobalPos 2025-03-08 09:58:16 +08:00
xiaoxijun
93e956372b Updated Upstream (Folia) 2025-03-07 13:17:09 +08:00
Dreeam
0bf38e65cf Updated Upstream (Folia) 2025-02-28 04:36:57 -05:00
Kercute
e5b2276a8d Updated Upstream (Folia) 2025-02-25 18:30:10 +08:00
HaHaWTH
589c263bac Configurable tripwire dupe
梦梦辛苦辽
2025-02-24 06:07:29 -08:00
M2ke4U
5d3d2271bc Merge pull request #55 from Suisuroru/suisuroru/descriptions-fix
Fix some syntax errors in configuration file descriptions and submit comments on container extension settings
2025-02-23 10:29:01 +08:00
Suisuroru
3361b9db14 feat(config): corrected words in some configuration descriptions 2025-02-23 02:17:42 +08:00
MrHua269
f6ca4cc24a [ci skip] Removed useless parts 2025-02-22 19:37:24 +08:00
MrHua269
85ffaa1156 Fix wrong upper-cased file name 2025-02-22 18:43:01 +08:00
MrHua269
6c48c27b7d Fixed end portal teleportation and added jenkins file 2025-02-22 18:38:44 +08:00
Dreeam
41770b069e Updated Upstream (Folia) 2025-02-22 03:48:09 -05:00
Suisuroru
d4c1790f94 Purpur: barrels and enderchests 6 rows
Merge Barrels-and-enderchests-6-rows of Purpur to luminol - #50
2025-02-20 22:35:02 +08:00
Creeam
4346983b7d [ci skip] Don't create release for PR jars 2025-02-20 15:25:17 +08:00
HaHaWTH
720e02e944 Updated Upstream (Folia) 2025-02-17 21:30:17 -08:00
HaHaWTH
f035a3bd8e Updated Upstream (Folia) 2025-02-17 09:08:35 -08:00
HaHaWTH
365a5252a9 Make SIMD actually work 2025-02-15 07:19:20 -08:00
Dreeam
5746a0e01c Updated Upstream (Folia) 2025-02-14 01:41:38 -05:00
MrHua269
8bce97d0bb Fix uncorrected death check of folia 2025-02-11 13:36:54 +08:00
MrHua269
8817720b5a Removed mis-added files 2025-02-11 12:25:24 +08:00
MrHua269
525b5ccfba Clean patches 2025-02-11 12:06:21 +08:00
MrHua269
821c69804d 1 2025-02-11 10:47:34 +08:00
MrHua269
cc840886f3 Updated Upstream(Folia) 2025-02-11 09:23:11 +08:00
MrHua269
70257fa22b [ci skip]Diff 2025-02-08 15:25:47 +08:00
MrHua269
40242ad8de Leaves Fix Incorrect Collision Behavior for Block Shape 2025-02-08 14:27:27 +08:00
Dreeam
08cf5d6179 Fix build time showed in version command 2025-02-07 11:11:04 -05:00
MrHua269
88eb84f82d Do not store tick count for living entities 2025-02-07 23:07:33 +08:00
MrHua269
19745cf033 Revert "Removed paper hopper optimizations"
This reverts commit 9ba08a6ce6.
2025-02-07 21:19:29 +08:00
MrHua269
9ba08a6ce6 Removed paper hopper optimizations 2025-02-06 23:19:17 +08:00
Klop233
2274af4415 [ci skip] Update readme 2025-02-05 16:39:22 +08:00
151 changed files with 3572 additions and 3463 deletions

View File

@@ -31,6 +31,7 @@ jobs:
- name: CreateJar
run: ./gradlew createMojmapPaperclipJar
- name: Publish to repo
if: github.event_name != 'pull_request'
continue-on-error: true
run: |
export MAVEN_REPO_USER=${{ secrets.MAVEN_REPO_USER }}
@@ -42,9 +43,10 @@ jobs:
name: "${{ env.project_id_b }} CI Artifacts"
path: "luminol-server/build/libs/*.jar"
- name: SetENV
if: github.event_name != 'pull_request'
run: sh scripts/SetENV.sh
- name: Create Release
if: "!contains(github.event.commits[0].message, '[release skip]')"
if: github.event_name != 'pull_request'
uses: ncipollo/release-action@v1.14.0
with:
tag: ${{ env.tag }}

3
.gitignore vendored
View File

@@ -10,9 +10,8 @@ build
/luminol-api/build.gradle.kts
/folia-server/build.gradle.kts
/folia-server/src/minecraft
/paper-server
/folia-api/build.gradle.kts
/paper-server
/paper-api
/paper-api-generator
.idea/

48
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,48 @@
pipeline {
agent any
stages {
stage('Configure git') {
steps {
script {
sh 'git config --global user.name "luminolmc"'
sh 'git config --global user.email "luminolmc@noreply.github.com"'
}
}
}
stage('Apply patches') {
steps {
script {
sh 'chmod +x gradlew'
sh './gradlew applyAllPatches'
}
}
}
stage('Build paperclip jar') {
steps {
script {
sh './gradlew createMojmapPaperclipJar'
}
}
}
stage('Upload artifacts') {
steps {
script {
archiveArtifacts(
artifacts: "luminol-server/build/libs/*.jar",
allowEmptyArchive: false
)
}
}
}
}
post {
always {
cleanWs()
}
}
}

View File

@@ -24,7 +24,7 @@
要构建一个paperclip jar你需要运行以下命令。你可以在build/libs中找到jar注意需要`JDK21`
```shell
./gradlew applyPatches && ./gradlew createMojmapPaperclipJar
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
```
## 使用API

View File

@@ -25,7 +25,7 @@ Any versions are available in the [release](https://github.com/LuminolMC/Luminol
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
./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar
```
## Using API

View File

@@ -2,7 +2,7 @@ group = me.earthme.luminol
version=1.21.4-R0.1-SNAPSHOT
mcVersion=1.21.4
foliaRef=3af04d9c6a98d24032bf8c99ad5446b0f381e320
foliaRef=d4cf71c327956e374a1e379535f9c47fb0ffc94a
org.gradle.configuration-cache=true
org.gradle.caching=true

View File

@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 29 Jan 2025 09:50:53 +0800
Date: Tue, 11 Feb 2025 09:16:49 +0800
Subject: [PATCH] KioCG Chunk API
@@ -16,13 +16,13 @@ index d434277342b2db19f98e032d3a316b27d728b840..e188353ad193f6203533790ae52fafc0
+ long getChunkHotAvg(); // KioCG
}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index dd043851687283f48af899d069d732425c794afd..ac5b7d030cbe3aae908fb2a0130cdf04d4924c18 100644
index 0081dd53b6a81ce7892e58d61f9f8a6718e30775..28fbd8df491a4c562de7530e88706e9c88460483 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -3928,4 +3928,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@@ -3902,4 +3902,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @return the result of this method, holding leftovers and spawned items.
*/
@NotNull PlayerGiveResult give(@NotNull Collection<@NotNull ItemStack> items, boolean dropIfFull);
PlayerGiveResult give(Collection<ItemStack> items, boolean dropIfFull);
+
+ long getNearbyChunkHot(); // KioCG
}

View File

@@ -6,10 +6,10 @@ Subject: [PATCH] Pufferfish SIMD Utilities
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
index 0000000000000000000000000000000000000000..856de1331b15542c00e01990f471fa5152722c11
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
@@ -0,0 +1,39 @@
@@ -0,0 +1,35 @@
+package gg.pufferfish.pufferfish.simd;
+
+import jdk.incubator.vector.FloatVector;
@@ -26,24 +26,20 @@ index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9
+ @Deprecated
+ public static boolean canEnable(Logger logger) {
+ try {
+ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) {
+ SIMDDetection.testRun = true;
+
+ VectorSpecies<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
+ VectorSpecies<Float> 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;
+ } else {
+ SIMDDetection.testRun = true;
+
+ VectorSpecies<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
+ VectorSpecies<Float> 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;
+ }
+
+ 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;
+ }
@@ -51,10 +47,10 @@ index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9
+}
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
index 0000000000000000000000000000000000000000..0a64cd0e88083ac4af6674ad0fb07b771109c737
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java
@@ -0,0 +1,35 @@
@@ -0,0 +1,34 @@
+package gg.pufferfish.pufferfish.simd;
+
+import org.slf4j.Logger;
@@ -63,7 +59,6 @@ index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae
+public class SIMDDetection {
+
+ public static boolean isEnabled = false;
+ public static boolean versionLimited = false;
+ public static boolean testRun = false;
+
+ @Deprecated
@@ -90,3 +85,118 @@ index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae
+ }
+
+}
diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java
new file mode 100644
index 0000000000000000000000000000000000000000..c26dcaaa2e85882730c854099df80d69eec70f33
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java
@@ -0,0 +1,84 @@
+package gg.pufferfish.pufferfish.simd;
+
+import jdk.incubator.vector.FloatVector;
+import jdk.incubator.vector.IntVector;
+import jdk.incubator.vector.VectorMask;
+import jdk.incubator.vector.VectorSpecies;
+import org.bukkit.map.MapPalette;
+
+import java.awt.*;
+
+@Deprecated
+public class VectorMapPalette {
+
+ private static final VectorSpecies<Integer> I_SPEC = IntVector.SPECIES_PREFERRED;
+ private static final VectorSpecies<Float> F_SPEC = FloatVector.SPECIES_PREFERRED;
+
+ @Deprecated
+ public static void matchColorVectorized(int[] in, byte[] out) {
+ int speciesLength = I_SPEC.length();
+ int i;
+ for (i = 0; i < in.length - speciesLength; i += speciesLength) {
+ float[] redsArr = new float[speciesLength];
+ float[] bluesArr = new float[speciesLength];
+ float[] greensArr = new float[speciesLength];
+ int[] alphasArr = new int[speciesLength];
+
+ for (int j = 0; j < speciesLength; j++) {
+ alphasArr[j] = (in[i + j] >> 24) & 0xFF;
+ redsArr[j] = (in[i + j] >> 16) & 0xFF;
+ greensArr[j] = (in[i + j] >> 8) & 0xFF;
+ bluesArr[j] = (in[i + j] >> 0) & 0xFF;
+ }
+
+ IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0);
+ FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0);
+ FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0);
+ FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0);
+ IntVector resultIndex = IntVector.zero(I_SPEC);
+ VectorMask<Integer> modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff);
+
+ modificationMask = modificationMask.and(alphas.lt(128).not());
+ FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE);
+
+ for (int c = 4; c < MapPalette.colors.length; c++) {
+ // We're using 32-bit floats here because it's 2x faster and nobody will know the difference.
+ // For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary.
+ FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed());
+ FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen());
+ FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue());
+
+ FloatVector rMean = reds.add(compReds).div(2.0f);
+ FloatVector rDiff = reds.sub(compReds);
+ FloatVector gDiff = greens.sub(compGreens);
+ FloatVector bDiff = blues.sub(compBlues);
+
+ FloatVector weightR = rMean.div(256.0f).add(2);
+ FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f);
+ FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f);
+
+ FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff));
+
+ // Now we compare to the best distance we've found.
+ // This mask contains a "1" if better, and a "0" otherwise.
+ VectorMask<Float> bestDistanceMask = distance.lt(bestDistances);
+ bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances
+
+ // Update the result array
+ // We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough.
+ resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results
+ }
+
+ for (int j = 0; j < speciesLength; j++) {
+ int index = resultIndex.lane(j);
+ out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127));
+ }
+ }
+
+ // For the final ones, fall back to the regular method
+ for (; i < in.length; i++) {
+ out[i] = MapPalette.matchColor(new Color(in[i], true));
+ }
+ }
+
+}
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
index 6995f9cc08d162e3adcd3a28f6bfa6d329661999..83ea70a16b4090a8c628784f2807cd16e7065103 100644
--- a/src/main/java/org/bukkit/map/MapPalette.java
+++ b/src/main/java/org/bukkit/map/MapPalette.java
@@ -45,7 +45,7 @@ public final class MapPalette {
}
@NotNull
- static final Color[] colors = {
+ public static final Color[] colors = { // Luminol - package-private -> public
c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0),
c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29),
c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86),
@@ -216,9 +216,11 @@ public final class MapPalette {
temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth());
byte[] result = new byte[temp.getWidth() * temp.getHeight()];
+ if ((mapColorCache != null && mapColorCache.isCached()) || !gg.pufferfish.pufferfish.simd.SIMDDetection.isEnabled) { // Luminol - Pufferfish - vectorized map color conversion
for (int i = 0; i < pixels.length; i++) {
result[i] = matchColor(new Color(pixels[i], true));
}
+ } else gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result); // Luminol - Pufferfish - vectorized map color conversion
return result;
}

View File

@@ -186,10 +186,10 @@ index 0000000000000000000000000000000000000000..ecde4462b08d701b8bff9f26902f1775
+ RegionStats getRegionStats();
+}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 8784842d14bbbe7dbde181e86782a0955be66924..f998f6f0d3017767aa4dde45a7e8aea5dd36fe99 100644
index 2729f71ac5525b7669fb7cc8719a75e5ce8d1dfc..9020f0781b399484e2acf0ad139b0b364e1c7a8f 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -4407,4 +4407,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@@ -4409,4 +4409,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
}
}
}

View File

@@ -67,8 +67,8 @@
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
@@ -200,6 +_,13 @@
implementation("me.lucko:spark-paper:1.10.119-SNAPSHOT")
@@ -201,26 +_,33 @@
implementation("me.lucko:spark-paper:1.10.119-20241121.092015-1")
}
+// Pufferfish Start
@@ -81,7 +81,13 @@
tasks.jar {
manifest {
val git = Git(rootProject.layout.projectDirectory.path)
@@ -212,14 +_,14 @@
val mcVersion = rootProject.providers.gradleProperty("mcVersion").get()
val build = System.getenv("BUILD_NUMBER") ?: null
- val buildTime = if (build != null) Instant.now() else Instant.EPOCH
+ val buildTime = Instant.now() // Always use current as build time
val gitHash = git.exec(providers, "rev-parse", "--short=7", "HEAD").get().trim()
val implementationVersion = "$mcVersion-${build ?: "DEV"}-$gitHash"
val date = git.exec(providers, "show", "-s", "--format=%ci", gitHash).get().trim()
val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim()
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
@@ -101,10 +107,11 @@
"Build-Number" to (build ?: ""),
"Build-Time" to buildTime.toString(),
"Git-Branch" to gitBranch,
@@ -350,3 +_,9 @@
@@ -351,3 +_,10 @@
classpath(tasks.createReobfPaperclipJar.flatMap { it.outputZip })
mainClass.set(null as String?)
}
+
+// Pufferfish Start
+tasks.withType<JavaCompile> {
+ val compilerArgs = options.compilerArgs

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:15:52 +0800
Subject: [PATCH] Add 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()) {

View File

@@ -5,7 +5,7 @@ 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
index 1e59c21d26baf50fd74bc99c04dbea0faede446a..26637b397b06c14445740a733d378a38a85e1875 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

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 11:29:49 +0800
Subject: [PATCH] KioCG Chunk API and display of chunkhot in tpsbar
Date: Sun, 12 Jan 2025 10:27:31 +0800
Subject: [PATCH] Add tpsbar with chunkhot membar and regionbar
diff --git a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
@@ -17,10 +17,10 @@ index 8d67b4629c69d3039b199aaad45533d1acde114e..f7bfeca4b11b9860241d5eb80b6df420
((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
index 46375fa81b36b89b79c22f0a7ac6d610ab1183d4..f2124edb487b1d5f6bdc7fa086814f870724363a 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1666,7 +1666,44 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1665,7 +1665,44 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia end - region threading
//this.tickCount++; // Folia - region threading
//this.tickRateManager.tick(); // Folia - region threading
@@ -65,11 +65,25 @@ index ff71466ec0848d16121e351e30c31bb419af8b99..330af9f4de1c72387326816065350e71
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/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 375f4a59333ee1d75fb1acb8c2cbada7866bd48e..3abe2881e8a80bd6c128e96b976deebe3ada4678 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -766,6 +766,9 @@ 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
+ me.earthme.luminol.functions.GlobalServerRegionBar.cancelBarUpdateTask(); //Luminol - Region bar
super.stopServer();
//Util.shutdownExecutors(); // Paper - Improved watchdog support; moved into super
SkullBlockEntity.clear();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8..887a12b0b33a24f77e3dc118688f9e5b14d6f62f 100644
index 7fb6cfe0484a4cc1e30fd8e344de307a0c734b68..f2d0d8c7577ea5d798b6a2cf8fd6282cead9de94 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
@@ -1339,6 +1339,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);
@@ -78,7 +92,7 @@ index ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8..887a12b0b33a24f77e3dc118688f9e5b
try {
// Folia end - profiler
if (isActive) { // Paper - EAR 2
@@ -1364,6 +1366,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1356,6 +1358,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
} else {entity.inactiveTick();} // Paper - EAR 2
profilerFiller.pop();
} finally { profiler.stopTimer(timerId); } // Folia - profiler
@@ -86,7 +100,7 @@ index ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8..887a12b0b33a24f77e3dc118688f9e5b
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
@@ -1375,6 +1378,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);
@@ -95,7 +109,7 @@ index ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8..887a12b0b33a24f77e3dc118688f9e5b
try {
// Folia end - profiler
passengerEntity.setOldPosAndRot();
@@ -1416,6 +1421,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1409,6 +1414,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.tickPassenger(passengerEntity, entity, isActive); // Paper - EAR 2
}
} finally { profiler.stopTimer(timerId); } // Folia - profiler
@@ -104,10 +118,21 @@ index ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8..887a12b0b33a24f77e3dc118688f9e5b
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index f1239f1a7b6b8fd958333df8092359eea7197fc0..9fd3fe181df2ce6dbe695f6463d3940ac4c01167 100644
index 423534a1ff02bd0d0f9baacfe2428f45c7d9acb9..9fd3fe181df2ce6dbe695f6463d3940ac4c01167 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1008,7 +1008,34 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -393,7 +393,9 @@ 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
+ public volatile boolean isMemBarVisible = false; //Luminol - Memory bar
+ public volatile boolean isRegionBarVisible = false; //Luminol - Region 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();
@@ -1006,8 +1008,35 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
this.trackEnteredOrExitedLavaOnVehicle();
this.updatePlayerAttributes();
this.advancements.flushDirty(this);
@@ -117,8 +142,8 @@ index f1239f1a7b6b8fd958333df8092359eea7197fc0..9fd3fe181df2ce6dbe695f6463d3940a
+ this.nearbyChunkHot = this.refreshNearbyChunkHot();
+ }
+ // KioCG end
+ }
+
}
+ // KioCG start - ChunkHot
+ private volatile long nearbyChunkHot = 0;
+
@@ -136,12 +161,13 @@ index f1239f1a7b6b8fd958333df8092359eea7197fc0..9fd3fe181df2ce6dbe695f6463d3940a
+ }
+ }
+ return total;
}
+ }
+ // KioCG end
+
+
private void updatePlayerAttributes() {
AttributeInstance attribute = this.getAttribute(Attributes.BLOCK_INTERACTION_RANGE);
if (attribute != null) {
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
@@ -159,10 +185,10 @@ index 23b342cc31c7e72ade0e1ccad86a9ccf34380f13..249cb7326c8e4012dcffdb6bbb7bfc1f
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 5979893976ab8c59a17e306cd91c9a4f5cd3738e..4f0ea00cd601c62926220400c8e3597815dc4d15 100644
index 26637b397b06c14445740a733d378a38a85e1875..0a7d6172d42f4b0395aa448b1c1d9fb8eaa4bf7a 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -5967,4 +5967,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -5919,4 +5919,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return ((ServerLevel) this.level).isPositionEntityTicking(this.blockPosition());
}
// Paper end - Expose entity id counter
@@ -234,10 +260,10 @@ index 6655d06e2011e20e7346dfe57527795269094d8a..48aa6fcb5c16fdbb4ae902cbb72c6b8e
+ // KioCG end
}
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 7635b16cf82577a4822a5057aa5319d4c23e2168..0e020dfebe06dce4c19beb10c961ea9e8a35a415 100644
index e70919757dee4b02384ded3551c8f580d289584a..ae049c5c3593525b991d865fec695c00ad408a59 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 {
@@ -1546,6 +1546,13 @@ public abstract class Player extends LivingEntity {
return true;
}

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
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();

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
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();

View File

@@ -5,7 +5,7 @@ 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 c6490516215ad94323174de81771f258cecc7742..ff2de692d397bf658fc7c8af0c6ce7697d1076a7 100644
index 3abe2881e8a80bd6c128e96b976deebe3ada4678..a0a8b0c7d091f63f023f15a2620b03ae2126782e 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

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: adabugra <57899270+adabugra@users.noreply.github.com>
Date: Fri, 31 Jan 2025 01:21:44 +0300
Subject: [PATCH] Add a simple regionbar
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index cc80198a5d5f4e9188ef35944d077200f03ac43b..c6490516215ad94323174de81771f258cecc7742 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -766,6 +766,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
public void stopServer() {
me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar
me.earthme.luminol.functions.GlobalServerMemoryBar.cancelBarUpdateTask(); //Luminol - Memory bar
+ me.earthme.luminol.functions.GlobalServerRegionBar.cancelBarUpdateTask(); //Luminol - Region 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 a07e02132bdda2693686440b9932992641cb6957..f1239f1a7b6b8fd958333df8092359eea7197fc0 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -395,6 +395,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
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
+ public volatile boolean isRegionBarVisible = false; //Luminol - Region 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();

View File

@@ -17,16 +17,3 @@ index 41a9cc693183e96c83837692e93b177a521d6789..f4a2d1a2d467808b9cb75fc32765ddc2
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);
}
}

View File

@@ -55,7 +55,7 @@ index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d
+ 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
index f2124edb487b1d5f6bdc7fa086814f870724363a..ed00a29daccfee1d631bef27c0a3a4ae83140018 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -986,10 +986,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

View File

@@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Sat, 8 Mar 2025 09:56:15 +0800
Subject: [PATCH] Add experiment config for entity to clean memory value which
is not belong to current tickregion
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
index 65b2b3ece213d901cdd585093e2fafcd2ef4a7cd..d61fba01feecce3610cd390f490d3097c5db19c4 100644
--- a/net/minecraft/world/entity/ai/Brain.java
+++ b/net/minecraft/world/entity/ai/Brain.java
@@ -399,7 +399,7 @@ public class Brain<E extends LivingEntity> {
}
public void tick(ServerLevel level, E entity) {
- this.forgetOutdatedMemories();
+ this.forgetOutdatedMemories(entity); // Luminol - Add config to force clean entity memory that don't belong to current tick region
this.tickSensors(level, entity);
this.startEachNonRunningBehavior(level, entity);
this.tickEachRunningBehavior(level, entity);
@@ -411,10 +411,31 @@ public class Brain<E extends LivingEntity> {
}
}
- private void forgetOutdatedMemories() {
+ private void forgetOutdatedMemories(E owner) { // Luminol - Add config to force clean entity memory that don't belong to current tick region
for (Entry<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> entry : this.memories.entrySet()) {
if (entry.getValue().isPresent()) {
ExpirableValue<?> expirableValue = (ExpirableValue<?>)entry.getValue().get();
+ // Luminol start - Add config to force clean entity memory that don't belong to current tick region
+ final Object value = expirableValue.getValue();
+ final net.minecraft.world.level.Level ownerLevel = owner.level();
+
+ // type: entity
+ if (me.earthme.luminol.config.modules.experiment.ForceCleanupEntityBrainMemoryConfig.enabledForEntity && value instanceof LivingEntity entity) {
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
+ this.eraseMemory(entry.getKey());
+ continue;
+ }
+ }
+
+ // type: block_pos
+ if (me.earthme.luminol.config.modules.experiment.ForceCleanupEntityBrainMemoryConfig.enabledForBlockPos && value instanceof net.minecraft.core.BlockPos blockPos) {
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(ownerLevel, blockPos)) {
+ this.eraseMemory(entry.getKey());
+ continue;
+ }
+ }
+ // Luminol end
+
if (expirableValue.hasExpired()) {
this.eraseMemory(entry.getKey());
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Teleport async if entity was moving to another region at once
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index c9730114f1d5dc1ecd6a38dbc7e5e936065dd92b..1868cb351d030d1997b5c81a184657085261c2f3 100644
index cc8efa162fbe7ce6a91629239bf18d7b6b096a8a..4026d465687604965f105ded21a8206fd52bd375 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
@@ -1100,6 +1100,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Paper end - detailed watchdog information
@@ -19,7 +19,7 @@ index c9730114f1d5dc1ecd6a38dbc7e5e936065dd92b..1868cb351d030d1997b5c81a18465708
public void move(MoverType type, Vec3 movement) {
final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity
// Paper start - detailed watchdog information
@@ -1109,6 +1113,32 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1110,6 +1114,32 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.moveStartZ = this.getZ();
this.moveVector = movement;
}

View File

@@ -5,7 +5,7 @@ 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
index ed00a29daccfee1d631bef27c0a3a4ae83140018..330af9f4de1c72387326816065350e71fe546efe 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -783,8 +783,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -65,7 +65,7 @@ index c00378ba258647787bb9138e319b0f6a0b00e1ed..ff71466ec0848d16121e351e30c31bb4
new com.destroystokyo.paper.event.server.ServerTickStartEvent((int)region.getCurrentTick()).callEvent(); // Paper - Server Tick Events // Folia - region threading
// Folia start - region threading
if (region != null) {
@@ -1706,7 +1707,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1743,7 +1744,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
long remaining = scheduledEnd - endTime; // Folia - region ticking
new com.destroystokyo.paper.event.server.ServerTickEndEvent((int)io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick(), ((double)(endTime - startTime) / 1000000D), remaining).callEvent(); // Folia - region ticking
// Paper end - Server Tick Events
@@ -75,7 +75,7 @@ index c00378ba258647787bb9138e319b0f6a0b00e1ed..ff71466ec0848d16121e351e30c31bb4
}
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index ff2de692d397bf658fc7c8af0c6ce7697d1076a7..5973e6f327d3557ca95f504fe7b1a6c227a3e15f 100644
index a0a8b0c7d091f63f023f15a2620b03ae2126782e..d7c922540b46e289395aeed514c98e43dc298e7b 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -214,7 +214,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface

View File

@@ -13,10 +13,10 @@ Related to mojang's bug fix:
https://bugs.mojang.com/browse/MC-92875
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index aa4337942b4b9b7dd746b9b9c5a052d626b1e72c..61814607a6c8e4ce8d07645f005ea8d53f624c95 100644
index 4026d465687604965f105ded21a8206fd52bd375..b324bea291e3a50cc20d1b380c13c586d56781c0 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1675,6 +1675,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1676,6 +1676,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return;
}

View File

@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 11 Feb 2025 13:34:47 +0800
Subject: [PATCH] Fix uncorrected death check of folia
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
index 50af953a4698a3c6e16b840fab764dd733b3fbc9..a9c058238819f3631d94ac306185e909821caf35 100644
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -679,7 +679,7 @@ public abstract class AbstractContainerMenu {
}
private static void dropOrPlaceInInventory(Player player, ItemStack stack) {
- boolean flag = player.isRemoved() && player.getRemovalReason() != Entity.RemovalReason.CHANGED_DIMENSION;
+ boolean flag = !player.isAlive(); //player.isRemoved() && player.getRemovalReason() != Entity.RemovalReason.CHANGED_DIMENSION; // Luminol - Fix uncorrected death check of folia
boolean flag1 = player instanceof ServerPlayer serverPlayer && serverPlayer.hasDisconnected();
if (flag || flag1) {
player.drop(stack, false);

View File

@@ -0,0 +1,85 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Sat, 8 Mar 2025 09:55:40 +0800
Subject: [PATCH] Fix a series issue around entity memory typed GlobalPos and
WalkTarget
diff --git a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
index 2664d72c3b6906d0505df2e63c0e5075eba9461b..f03c3c512ea48c2a89eebae62484922d28e4f831 100644
--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
+++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
@@ -69,6 +69,11 @@ public class BehaviorUtils {
}
public static void setWalkAndLookTargetMemories(LivingEntity entity, PositionTracker positionTracker, float speedModifier, int closeEnoughDist) {
+ // Luminol - Do not set walk target if target position is out of current tick region
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity.level(), positionTracker.currentBlockPosition())) {
+ return;
+ }
+ // Luminol end
WalkTarget walkTarget = new WalkTarget(positionTracker, speedModifier, closeEnoughDist);
entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, positionTracker);
entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, walkTarget);
diff --git a/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
index bc6a5cacd67d46e0beb97adf30d98c1034be1a44..dd35eef062c36a409b6d3e701664db504c4c7631 100644
--- a/net/minecraft/world/entity/ai/behavior/SleepInBed.java
+++ b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
@@ -42,6 +42,12 @@ public class SleepInBed extends Behavior<LivingEntity> {
}
}
+ // Luminol - Prevent off-tick-region chunk operations
+ final net.minecraft.world.level.Level currentLevel = owner.level();
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(currentLevel, globalPos.pos())) {
+ return false;
+ }
+ // Luminol -end
BlockState blockState = level.getBlockStateIfLoaded(globalPos.pos()); // Paper - Prevent sync chunk loads when villagers try to find beds
if (blockState == null) { return false; } // Paper - Prevent sync chunk loads when villagers try to find beds
return globalPos.pos().closerToCenterThan(owner.position(), 2.0) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
diff --git a/net/minecraft/world/entity/animal/allay/AllayAi.java b/net/minecraft/world/entity/animal/allay/AllayAi.java
index 36a9887f8be04c5c3fda6d926d819a9e5b2a79f2..5681592bdeb050d875c4c5d0dfaf6e015beb1c74 100644
--- a/net/minecraft/world/entity/animal/allay/AllayAi.java
+++ b/net/minecraft/world/entity/animal/allay/AllayAi.java
@@ -114,6 +114,17 @@ public class AllayAi {
Optional<GlobalPos> memory = brain.getMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION);
if (memory.isPresent()) {
GlobalPos globalPos = memory.get();
+ // Luminol start - Do not like item if they were out of current tickregion
+ final Level targetLevel = entity.level().getServer().getLevel(globalPos.dimension());
+ final BlockPos targetPos = globalPos.pos();
+
+ // thread checks
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(targetLevel, targetPos)) {
+ brain.eraseMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION); // The memory value is not being belong to current tick region anymore
+ return Optional.empty();
+ }
+ // Luminol end
+
if (shouldDepositItemsAtLikedNoteblock(entity, brain, globalPos)) {
return Optional.of(new BlockPosTracker(globalPos.pos().above()));
}
diff --git a/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
index 62ca7871d1e5d0fe611948ad43e44c23fdc2d3f8..cd0fc85fbefce4669b4cb637ec3b2628da57adbf 100644
--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java
+++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
@@ -257,7 +257,17 @@ public class Sniffer extends Animal {
private boolean canDig(BlockPos pos) {
return this.level().getBlockState(pos).is(BlockTags.SNIFFER_DIGGABLE_BLOCK)
- && this.getExploredPositions().noneMatch(globalPos -> GlobalPos.of(this.level().dimension(), pos).equals(globalPos))
+ && this.getExploredPositions().noneMatch(globalPos -> { // Luminol start - Do not pathfind out of tickregion
+ // thread checks
+ final Level targetLevel = net.minecraft.server.MinecraftServer.getServer().getLevel(globalPos.dimension());
+ final BlockPos targetPos = globalPos.pos();
+
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(targetLevel, targetPos)) {
+ return false;
+ }
+
+ return GlobalPos.of(this.level().dimension(), pos).equals(globalPos); // Original logic
+ }) // Luminol end
&& Optional.ofNullable(this.getNavigation().createPath(pos, 1)).map(Path::canReach).orElse(false);
}

View File

@@ -5,24 +5,16 @@ Subject: [PATCH] Kaiiju Vanilla end portal teleportation
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 61814607a6c8e4ce8d07645f005ea8d53f624c95..5979893976ab8c59a17e306cd91c9a4f5cd3738e 100644
index b324bea291e3a50cc20d1b380c13c586d56781c0..46460af3ebd76d7475aa7a7cbe55203a40f1c323 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;
+import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.entity.EntityAccess;
import net.minecraft.world.level.entity.EntityInLevelCallback;
import net.minecraft.world.level.gameevent.DynamicGameEventListener;
@@ -4280,13 +4281,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4281,14 +4281,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) -> {
- net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, targetPos.below(), true, null);
-
+ //net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, targetPos.below(), true, null); // Kaiiju - Vanilla end teleportation - moved down
+ // Kaiiju start - Vanilla end teleportation
+ Vec3 finalPos;
+ if (this instanceof Player) finalPos = Vec3.atBottomCenterOf(targetPos.below());
@@ -32,23 +24,43 @@ index 61814607a6c8e4ce8d07645f005ea8d53f624c95..5979893976ab8c59a17e306cd91c9a4f
// on the obsidian, we need to spawn at targetPos.y - 1
portalInfoCompletable.complete(
new net.minecraft.world.level.portal.TeleportTransition(
- destination, Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, 90.0f, 0.0f,
+ destination, finalPos, this.getDeltaMovement(), 90.0f, 0.0f, // Kaiiju - Vanilla end teleportation
- destination, Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, Direction.WEST.toYRot(), 0.0f,
- Relative.union(Relative.DELTA, Set.of(Relative.X_ROT)),
+ destination, finalPos, this.getDeltaMovement(), Direction.WEST.toYRot(), 0.0f, // Kaiiju - Vanilla end teleportation
+ //Relative.union(Relative.DELTA, Set.of(Relative.X_ROT)), // Kaiiju - Vanilla end teleportation
TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET),
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL
)
@@ -4482,6 +4488,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4303,11 +4307,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
ca.spottedleaf.concurrentutil.util.Priority.HIGH,
(chunks) -> {
BlockPos adjustedSpawn = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, spawnPos);
-
+ // Kaiiju start - Vanilla end teleportation
+ Vec3 finalPos;
+ if (this instanceof Player) finalPos = Vec3.atBottomCenterOf(adjustedSpawn.below());
+ else finalPos = Vec3.atBottomCenterOf(adjustedSpawn);
+ // Kaiiju end
// done
portalInfoCompletable.complete(
new net.minecraft.world.level.portal.TeleportTransition(
- destination, Vec3.atBottomCenterOf(adjustedSpawn), Vec3.ZERO, 0.0f, 0.0f,
+ destination, finalPos, this.getDeltaMovement(), 0.0f, 0.0f, // Kaiiju - Vanilla end teleportation
Relative.union(Relative.DELTA, Relative.ROTATION),
TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET),
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL
@@ -4485,6 +4493,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (!this.canPortalAsync(destination, takePassengers)) {
return false;
}
+ // Kaiiju start - sync end platform spawning & entity teleportation
+ final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == LevelStem.END ?
+ final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END ?
+ e -> net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, ServerLevel.END_SPAWN_POINT.below(), true, null) : teleportComplete;
+ // Kaiiju end
Vec3 initialPosition = this.position();
ChunkPos initialPositionChunk = new ChunkPos(
@@ -4546,9 +4556,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4549,9 +4561,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
info.postTeleportTransition().onTransition(teleported);
}

View File

@@ -17,7 +17,7 @@ index c6e487a4c14e6b82533881d01f32349b9ae28728..2c747cb8a724cd25c9d724908f92b320
// block ticking
private final ObjectLinkedOpenHashSet<BlockEventData> blockEvents = new ObjectLinkedOpenHashSet<>();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index d34ad333b6ea3855a24a58fcd80ccf19b2bbf41c..ad121d609bcc1d9b53a1a20d4e25cf9dfa480fb8 100644
index f2d0d8c7577ea5d798b6a2cf8fd6282cead9de94..c768279df8551498a61d29630f4374f1054a2d8b 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

View File

@@ -18,7 +18,7 @@ index c260741a87513b89a5cc62c543fb9f990f86491e..beb9b3b3cd5ca60bd2cdada937bff8a1
}
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 d50aef6307fb854c8d4f66bb622cdafc43dce0ae..b6c820ebdc42edc1f3ce5c18eee5bff2e3822437 100644
index 6258b008ad3e00d41e9f3014572d6f7a06b1847c..2293c3db45e9ecce4e0d4b2f87b8e90228e44d94 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2044,6 +2044,20 @@ public abstract class LivingEntity extends Entity implements Attackable {

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Gale Skip entity move if movement is zero
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 4f0ea00cd601c62926220400c8e3597815dc4d15..a826320496a7a211cc07518adedfec9bdf8728b8 100644
index 46460af3ebd76d7475aa7a7cbe55203a40f1c323..72934a95991d25152e93c9b70e9992254d0daf23 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1104,7 +1104,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -23,7 +23,7 @@ index 4f0ea00cd601c62926220400c8e3597815dc4d15..a826320496a7a211cc07518adedfec9b
final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity
// Paper start - detailed watchdog information
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot move an entity off-main");
@@ -5046,6 +5053,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -5051,6 +5058,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public final void setBoundingBox(AABB bb) {

View File

@@ -62,7 +62,7 @@ index ac06b8a4813716a8d136be5731cbd96113976a7e..82d95005fc67336458b50c47d44ec404
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 887a12b0b33a24f77e3dc118688f9e5b14d6f62f..12f6c929c0168ea5b3242ff7139f1eac8b4e3a4b 100644
index c768279df8551498a61d29630f4374f1054a2d8b..31a1e2d9287654418563f4cb97a17bca42d17e64 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -620,6 +620,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe

View File

@@ -19,7 +19,7 @@ index 9fd3fe181df2ce6dbe695f6463d3940ac4c01167..822d401150d3764004b2570da828b4f6
);
});
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a826320496a7a211cc07518adedfec9bdf8728b8..6f9cfd8c72853d9cb30c9731a96e7f1e8f0644c4 100644
index 72934a95991d25152e93c9b70e9992254d0daf23..b99b5830a3e5bdbb781c7bcb8544b2e57415b5f5 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -4166,6 +4166,31 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -94,7 +94,7 @@ index a826320496a7a211cc07518adedfec9bdf8728b8..6f9cfd8c72853d9cb30c9731a96e7f1e
// need to load chunk for heightmap
destination.moonrise$loadChunksAsync(
spawnPos, 0,
@@ -4357,8 +4404,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4362,8 +4409,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
WorldBorder destinationBorder = destination.getWorldBorder();
double dimensionScale = net.minecraft.world.level.dimension.DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType());
@@ -114,7 +114,7 @@ index a826320496a7a211cc07518adedfec9bdf8728b8..6f9cfd8c72853d9cb30c9731a96e7f1e
ca.spottedleaf.concurrentutil.completable.CallbackCompletable<BlockUtil.FoundRectangle> portalFound
= new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>();
@@ -4495,9 +4552,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4500,9 +4557,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (!this.canPortalAsync(destination, takePassengers)) {
return false;
}
@@ -128,13 +128,13 @@ index a826320496a7a211cc07518adedfec9bdf8728b8..6f9cfd8c72853d9cb30c9731a96e7f1e
+ }
+ // Luminol end
// Kaiiju start - sync end platform spawning & entity teleportation
final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == LevelStem.END ?
final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END ?
- e -> net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, ServerLevel.END_SPAWN_POINT.below(), true, null) : teleportComplete;
+ e -> { if (new me.earthme.luminol.api.portal.EndPlatformCreateEvent().callEvent() && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(e.level, ServerLevel.END_SPAWN_POINT.below())) net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, ServerLevel.END_SPAWN_POINT.below(), true, null); } : teleportComplete; // Luminol - Add missing teleportation events & Fix teleportation api threading issue
// Kaiiju end
Vec3 initialPosition = this.position();
@@ -4571,6 +4637,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4576,6 +4642,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
tpComplete.accept(teleported);
}
// Kaiiju end

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Leaves Disable moved wrongly threshold
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 8c822dffc114b6aa6ddf2443606a1f9dc9262c45..60d8e9aca76614ca4ed235e96e0e9867a40e8bf5 100644
index 4e3cb90558533ea7ca0c838745e91ec5860c11ce..9fc72689b5021d1de2e149c1dfe5fc60048c7231 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -579,7 +579,7 @@ public class ServerGamePacketListenerImpl

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sat, 8 Feb 2025 14:25:16 +0800
Subject: [PATCH] Leaves Fix Incorrect Collision Behavior for Block Shape
diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
index 471b6d49d77e03665ffc269d17ab46f225e3ce1c..c574f9a23868a35ef694e432ba581d2f00e39da7 100644
--- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
+++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
@@ -101,6 +101,14 @@ public final class CollisionUtil {
(box1.minZ - box2.maxZ) < -COLLISION_EPSILON && (box1.maxZ - box2.minZ) > COLLISION_EPSILON;
}
+ // Leaves start
+ public static boolean voxelShapeIntersectVanilla(final net.minecraft.world.phys.AABB box1, final net.minecraft.world.phys.AABB box2) {
+ return box1.minX < box2.maxX && box1.maxX > box2.minX &&
+ box1.minY < box2.maxY && box1.maxY > box2.minY &&
+ box1.minZ < box2.maxZ && box1.maxZ > box2.minZ;
+ }
+ // Leaves end
+
// assume !isEmpty(target) && abs(source_move) >= COLLISION_EPSILON
public static double collideX(final AABB target, final AABB source, final double source_move) {
if ((source.minY - target.maxY) < -COLLISION_EPSILON && (source.maxY - target.minY) > COLLISION_EPSILON &&
@@ -2026,7 +2034,10 @@ public final class CollisionUtil {
AABB singleAABB = ((CollisionVoxelShape)blockCollision).moonrise$getSingleAABBRepresentation();
if (singleAABB != null) {
singleAABB = singleAABB.move((double)blockX, (double)blockY, (double)blockZ);
- if (!voxelShapeIntersect(aabb, singleAABB)) {
+ // Leaves start - Fix incorrect collision behavior for block shape
+ boolean isBlockShape = blockCollision == net.minecraft.world.phys.shapes.Shapes.block();
+ if (isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB)) {
+ // Leaves end - Fix incorrect collision behavior for block shape
continue;
}

View File

@@ -5,7 +5,6 @@ Subject: [PATCH] Raytracing tracker experiment
Based on the framework of EntityCulling(((((((
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 7eff847790394aecd058e7a61905da86163b4c6e..9099457f55a2829297ac1db8a69a98ff717d9a86 100644
--- a/net/minecraft/server/level/ChunkMap.java
@@ -20,10 +19,10 @@ index 7eff847790394aecd058e7a61905da86163b4c6e..9099457f55a2829297ac1db8a69a98ff
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 6f9cfd8c72853d9cb30c9731a96e7f1e8f0644c4..b1ded501047f75d2e7af775bf8866fd6a5400a91 100644
index b99b5830a3e5bdbb781c7bcb8544b2e57415b5f5..a570499366ff238c869de60be3aeed0459b73db8 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -136,7 +136,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
import net.minecraft.world.scores.Team;
import org.slf4j.Logger;
@@ -32,7 +31,7 @@ index 6f9cfd8c72853d9cb30c9731a96e7f1e8f0644c4..b1ded501047f75d2e7af775bf8866fd6
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
@@ -6050,4 +6050,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -6055,4 +6055,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -94,7 +93,7 @@ index d9cc1d7e56c37d5ce92544edc10e89dbc89dd15d..39e7689be243b9c99b507d665f659135
public EntityType(
EntityType.EntityFactory<T> factory,
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 0e020dfebe06dce4c19beb10c961ea9e8a35a415..49f927c20b84e47ed2b0e57beecb3aa746448f5a 100644
index ae049c5c3593525b991d865fec695c00ad408a59..ad34d0e1ab16fb269b3cec2842bfc2f2c29b452e 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -210,6 +210,25 @@ public abstract class Player extends LivingEntity {
@@ -150,7 +149,7 @@ index 0e020dfebe06dce4c19beb10c961ea9e8a35a415..49f927c20b84e47ed2b0e57beecb3aa7
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
@@ -1502,6 +1541,7 @@ public abstract class Player extends LivingEntity {
@@ -1504,6 +1543,7 @@ public abstract class Player extends LivingEntity {
if (this.containerMenu != null && this.hasContainerOpen()) {
this.doCloseContainer();
}

View File

@@ -0,0 +1,172 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Suisuroru <qwertyuiop14077@qq.com>
Date: Thu, 20 Feb 2025 01:00:28 +0800
Subject: [PATCH] Purpur-Barrels-and-enderchests-6-rows
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 548f7a2b0b020ff7fff27396942cc0bc9e755afe..b977d0b2c754c227b667ce9fdd3ebb934db8e974 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1103,6 +1103,10 @@ public abstract class PlayerList {
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
} // Paper - Add sendOpLevel API
+
+ // Purpur start - Barrels and enderchests 6 rows
+ player.enderChestSlotCount = me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27;
+ // Purpur end - Barrels and enderchests 6 rows
}
public boolean isWhiteListed(GameProfile profile) {
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index ad34d0e1ab16fb269b3cec2842bfc2f2c29b452e..40b91234fd2e4f4f134d309590ea6b605f764e83 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -200,6 +200,7 @@ public abstract class Player extends LivingEntity {
private int currentImpulseContextResetGraceTime;
public boolean affectsSpawning = true; // Paper - Affects Spawning API
public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
+ public int enderChestSlotCount = -1; // Purpur - Barrels and enderchests 6 rows
// CraftBukkit start
public boolean fauxSleeping;
diff --git a/net/minecraft/world/inventory/ChestMenu.java b/net/minecraft/world/inventory/ChestMenu.java
index 280169afbd637eeb67ddf7eaeb4eecd464a128d5..461705345dd897c8304c884272531af836f8854f 100644
--- a/net/minecraft/world/inventory/ChestMenu.java
+++ b/net/minecraft/world/inventory/ChestMenu.java
@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu {
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, 6);
}
+ // Purpur start - Barrels and enderchests 6 rows
+ public static ChestMenu oneRow(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x1, syncId, playerInventory, inventory, 1);
+ }
+
+ public static ChestMenu twoRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x2, syncId, playerInventory, inventory, 2);
+ }
+ // Purpur end - Barrels and enderchests 6 rows
+
public static ChestMenu threeRows(int containerId, Inventory playerInventory, Container container) {
return new ChestMenu(MenuType.GENERIC_9x3, containerId, playerInventory, container, 3);
}
+ // Purpur start - Barrels and enderchests 6 rows
+ public static ChestMenu fourRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x4, syncId, playerInventory, inventory, 4);
+ }
+
+ public static ChestMenu fiveRows(int syncId, Inventory playerInventory, Container inventory) {
+ return new ChestMenu(MenuType.GENERIC_9x5, syncId, playerInventory, inventory, 5);
+ }
+ // Purpur end - Barrels and enderchests 6 rows
+
public static ChestMenu sixRows(int containerId, Inventory playerInventory, Container container) {
return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6);
}
diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
index a6a359bab2a727f4631b633a8bb370dd40decc75..5fab998cdec92a2bd965e6b48cc6189b195dc86d 100644
--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java
+++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java
@@ -25,11 +25,18 @@ public class PlayerEnderChestContainer extends SimpleContainer {
}
public PlayerEnderChestContainer(Player owner) {
- super(27);
+ super(me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27);
this.owner = owner;
// CraftBukkit end
}
+ // Purpur start - Barrels and enderchests 6 rows
+ @Override
+ public int getContainerSize() {
+ return owner.enderChestSlotCount < 0 ? super.getContainerSize() : owner.enderChestSlotCount;
+ }
+ // Purpur end - Barrels and enderchests 6 rows
+
public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) {
this.activeChest = enderChestBlockEntity;
}
diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java
index f5533960708bdbaf2eacefbc7c7c3123b7d26502..bf9801f1370c8d5e6ca459207b221ef2e92dac9e 100644
--- a/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
@@ -85,8 +85,14 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
enderChestInventory.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
if (level instanceof ServerLevel serverLevel && player.openMenu(
new SimpleMenuProvider(
- (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE
- )
+ (containerId, playerInventory, player1) -> switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ case 6 -> ChestMenu.sixRows(containerId, playerInventory, enderChestInventory);
+ case 5 -> ChestMenu.fiveRows(containerId, playerInventory, enderChestInventory);
+ case 4 -> ChestMenu.fourRows(containerId, playerInventory, enderChestInventory);
+ case 2 -> ChestMenu.twoRows(containerId, playerInventory, enderChestInventory);
+ case 1 -> ChestMenu.oneRow(containerId, playerInventory, enderChestInventory);
+ default -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory);
+ }, CONTAINER_TITLE) // Purpur - Barrels and enderchests 6 rows
).isPresent()) {
// Paper end - Fix InventoryOpenEvent cancellation - moved up;
player.awardStat(Stats.OPEN_ENDERCHEST);
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
index 0f808855f58281578c2758513787f0f7330c9291..5b6ee21c21686dad86717b87c0033149cefad142 100644
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
@@ -55,7 +55,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
this.maxStack = i;
}
// CraftBukkit end
- private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
+ // Purpur start - Barrels and enderchests 6 rows
+ private NonNullList<ItemStack> items = NonNullList.withSize(switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
+ case 2 -> 18;
+ case 1 -> 9;
+ default -> 27;
+ }, ItemStack.EMPTY);
+ // Purpur end - Barrels and enderchests 6 rows
+
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
@Override
protected void onOpen(Level level, BlockPos pos, BlockState state) {
@@ -107,7 +117,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
@Override
public int getContainerSize() {
- return 27;
+ // Purpur start - Barrels and enderchests 6 rows
+ return switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> 54;
+ case 5 -> 45;
+ case 4 -> 36;
+ case 2 -> 18;
+ case 1 -> 9;
+ default -> 27;
+ };
+ // Purpur end - Barrels and enderchests 6 rows
}
@Override
@@ -127,7 +146,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
@Override
protected AbstractContainerMenu createMenu(int id, Inventory player) {
- return ChestMenu.threeRows(id, player, this);
+ // Purpur start - Barrels and enderchests 6 rows
+ return switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> ChestMenu.sixRows(id, player, this);
+ case 5 -> ChestMenu.fiveRows(id, player, this);
+ case 4 -> ChestMenu.fourRows(id, player, this);
+ case 2 -> ChestMenu.twoRows(id, player, this);
+ case 1 -> ChestMenu.oneRow(id, player, this);
+ default -> ChestMenu.threeRows(id, player, this);
+ };
+ // Purpur end - Barrels and enderchests 6 rows
}
@Override

View File

@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
Date: Mon, 24 Feb 2025 06:00:00 -0800
Subject: [PATCH] Configurable tripwire dupe
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
index 9aace993c6c18f1a50610e4766225485984b8167..07ffe289b9556b45a9ef7db5357d85b14fe23feb 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.AllowTripwireDupe.enabled || blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) {
if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3); // Paper - prevent tripwire from updating
}
}

View File

@@ -0,0 +1,10 @@
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -108,6 +_,7 @@
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();

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -212,6 +_,8 @@
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()) {

View File

@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:17:53 +0800
Date: Tue, 11 Feb 2025 11:58:56 +0800
Subject: [PATCH] Add config for server mod name
@@ -17,32 +17,3 @@ index 6ed2114f577ce12d2d493985e798609c7d83f15e..7a5dcf3b7108794b9a224004730eb396
this.server = server;
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..94e7c8910e3623163528a844fd7a08b3ffe5826b
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
@@ -0,0 +1,23 @@
+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 ServerModNameConfig implements IConfigModule {
+ @ConfigInfo(baseName = "name")
+ public static String serverModName = "Luminol";
+
+ @ConfigInfo(baseName = "vanilla_spoof")
+ public static boolean fakeVanilla = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "server_mod_name";
+ }
+}

View File

@@ -1,571 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:15:53 +0800
Subject: [PATCH] Add luminol config framework
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
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
@@ -0,0 +1,70 @@
+package me.earthme.luminol.commands;
+
+import me.earthme.luminol.config.LuminolConfig;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.TextColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LuminolConfigCommand extends Command {
+ public LuminolConfigCommand(){
+ super("luminolconfig");
+ this.setPermission("luminol.commands.luminolconfig");
+ this.setDescription("Manage config file");
+ this.setUsage("/luminolconfig");
+ }
+
+ @Override
+ public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) throws IllegalArgumentException {
+ final List<String> result = new ArrayList<>();
+
+ if (args.length == 1){
+ result.add("reload");
+ }
+
+ return result;
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
+ if (!this.testPermission(sender)){
+ sender.sendMessage(Component
+ .text("No permission to execute this command!")
+ .color(TextColor.color(255,0,0))
+ );
+ }
+
+ if (args.length < 1){
+ sender.sendMessage(
+ Component
+ .text("Wrong use!\n")
+ .color(TextColor.color(255,0,0))
+ );
+ return true;
+ }
+
+ switch (args[0]){
+ case "reload" -> {
+ LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ Component
+ .text("Reloaded config file!")
+ .color(TextColor.color(0,255,0))
+ ));
+ }
+
+ default -> sender.sendMessage(
+ Component
+ .text("Unknown action!\n")
+ .color(TextColor.color(255,0,0))
+ );
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/config/ConfigInfo.java b/src/main/java/me/earthme/luminol/config/ConfigInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..01b64c2cf6b437114337626c242e1da3fbdb8ead
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/ConfigInfo.java
@@ -0,0 +1,11 @@
+package me.earthme.luminol.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ConfigInfo {
+ String baseName();
+
+ String comments() default "";
+}
diff --git a/src/main/java/me/earthme/luminol/config/DoNotLoad.java b/src/main/java/me/earthme/luminol/config/DoNotLoad.java
new file mode 100644
index 0000000000000000000000000000000000000000..fffc5eb4be4b78a886f3c340bd60f3a2b0108a7d
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/DoNotLoad.java
@@ -0,0 +1,8 @@
+package me.earthme.luminol.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DoNotLoad {
+}
diff --git a/src/main/java/me/earthme/luminol/config/EnumConfigCategory.java b/src/main/java/me/earthme/luminol/config/EnumConfigCategory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b75405c468d24ed8aea5aa54ae5ac339118bf60
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/EnumConfigCategory.java
@@ -0,0 +1,19 @@
+package me.earthme.luminol.config;
+
+public enum EnumConfigCategory {
+ OPTIMIZATIONS("optimizations"),
+ FIXES("fixes"),
+ MISC("misc"),
+ GAMEPLAY("gameplay"),
+ EXPERIMENT("experiment");
+
+ private final String baseKeyName;
+
+ EnumConfigCategory(String baseKeyName) {
+ this.baseKeyName = baseKeyName;
+ }
+
+ public String getBaseKeyName() {
+ return this.baseKeyName;
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/config/HotReloadUnsupported.java b/src/main/java/me/earthme/luminol/config/HotReloadUnsupported.java
new file mode 100644
index 0000000000000000000000000000000000000000..559c11cb523c7cade34a0abfad15c988f5ad87fe
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/HotReloadUnsupported.java
@@ -0,0 +1,8 @@
+package me.earthme.luminol.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HotReloadUnsupported {
+}
diff --git a/src/main/java/me/earthme/luminol/config/IConfigModule.java b/src/main/java/me/earthme/luminol/config/IConfigModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f6896711907ac30fe0c00130207b970007e4bb4
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/IConfigModule.java
@@ -0,0 +1,22 @@
+package me.earthme.luminol.config;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import org.jetbrains.annotations.NotNull;
+
+public interface IConfigModule {
+
+ EnumConfigCategory getCategory();
+
+ String getBaseName();
+
+ default void onLoaded(CommentedFileConfig configInstance) {}
+
+ default <T> T get(String keyName, T defaultValue, @NotNull CommentedFileConfig config){
+ if (!config.contains(keyName)){
+ config.set(keyName,defaultValue);
+ return defaultValue;
+ }
+
+ return config.get(keyName);
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/config/LuminolConfig.java b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..526b68e184a2f6f9e38cd02995b473a943404141
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
@@ -0,0 +1,226 @@
+package me.earthme.luminol.config;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import io.papermc.paper.threadedregions.RegionizedServer;
+import me.earthme.luminol.commands.LuminolConfigCommand;
+import org.bukkit.Bukkit;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class LuminolConfig {
+ public static final Logger logger = LogManager.getLogger();
+ private static final File baseConfigFolder = new File("luminol_config");
+ private static final File baseConfigFile = new File(baseConfigFolder,"luminol_global_config.toml");
+ private static final Set<IConfigModule> allInstanced = new HashSet<>();
+ private static CommentedFileConfig configFileInstance;
+ public static boolean alreadyInited = false;
+
+ public static void setupLatch(){
+ Bukkit.getCommandMap().register("luminolconfig","luminol",new LuminolConfigCommand());
+ alreadyInited = true;
+ }
+
+ public static void reload(){
+ RegionizedServer.ensureGlobalTickThread("Reload luminol config off global region thread!");
+
+ dropAllInstanced();
+ try {
+ preLoadConfig();
+ finalizeLoadConfig();
+ }catch (Exception e){
+ logger.error(e);
+ }
+ }
+
+ @Contract(" -> new")
+ public static @NotNull CompletableFuture<Void> reloadAsync(){
+ return CompletableFuture.runAsync(LuminolConfig::reload,task -> RegionizedServer.getInstance().addTask(() -> {
+ try{
+ task.run();
+ }catch (Exception e){
+ logger.error(e);
+ }
+ }));
+ }
+
+ public static void dropAllInstanced(){
+ allInstanced.clear();
+ }
+
+ public static void finalizeLoadConfig() {
+ for (IConfigModule module : allInstanced) {
+ module.onLoaded(configFileInstance);
+ }
+ }
+
+ public static void preLoadConfig() throws IOException {
+ baseConfigFolder.mkdirs();
+
+ if (!baseConfigFile.exists()){
+ baseConfigFile.createNewFile();
+ }
+
+ configFileInstance = CommentedFileConfig.ofConcurrent(baseConfigFile);
+
+ configFileInstance.load();
+
+ try {
+ instanceAllModule();
+ loadAllModules();
+ }catch (Exception e){
+ logger.error("Failed to load config modules!",e);
+ throw new RuntimeException(e);
+ }
+
+ configFileInstance.save();
+ }
+
+ private static void loadAllModules() throws IllegalAccessException {
+ for (IConfigModule instanced : allInstanced){
+ loadForSingle(instanced);
+ }
+ }
+
+ private static void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ for (Class<?> clazz : getClasses("me.earthme.luminol.config.modules")){
+ if (IConfigModule.class.isAssignableFrom(clazz)){
+ allInstanced.add((IConfigModule) clazz.getConstructor().newInstance());
+ }
+ }
+ }
+
+ private static void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException {
+ final EnumConfigCategory category = singleConfigModule.getCategory();
+
+ Field[] fields = singleConfigModule.getClass().getDeclaredFields();
+
+ for (Field field : fields) {
+ int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
+ boolean skipLoad = field.getAnnotation(DoNotLoad.class) != null || (alreadyInited && field.getAnnotation(HotReloadUnsupported.class) != null);
+ ConfigInfo configInfo = field.getAnnotation(ConfigInfo.class);
+
+ if (skipLoad || configInfo == null){
+ continue;
+ }
+
+ final String fullConfigKeyName = category.getBaseKeyName() + "." + singleConfigModule.getBaseName() + "." + configInfo.baseName();
+
+ field.setAccessible(true);
+ final Object currentValue = field.get(null);
+
+ if (!configFileInstance.contains(fullConfigKeyName)){
+ if (currentValue == null){
+ throw new UnsupportedOperationException("Config " + singleConfigModule.getBaseName() + "tried to add an null default value!");
+ }
+
+ final String comments = configInfo.comments();
+
+ if (!comments.isBlank()){
+ configFileInstance.setComment(fullConfigKeyName,comments);
+ }
+
+ configFileInstance.add(fullConfigKeyName,currentValue);
+ continue;
+ }
+
+ final Object actuallyValue = configFileInstance.get(fullConfigKeyName);
+ field.set(null,actuallyValue);
+ }
+ }
+ }
+
+ public static @NotNull Set<Class<?>> getClasses(String pack) {
+ Set<Class<?>> classes = new LinkedHashSet<>();
+ String packageDirName = pack.replace('.', '/');
+ Enumeration<URL> dirs;
+
+ try {
+ dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
+ while (dirs.hasMoreElements()) {
+ URL url = dirs.nextElement();
+ String protocol = url.getProtocol();
+ if ("file".equals(protocol)) {
+ String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8);
+ findClassesInPackageByFile(pack, filePath, classes);
+ } else if ("jar".equals(protocol)) {
+ JarFile jar;
+ try {
+ jar = ((JarURLConnection) url.openConnection()).getJarFile();
+ Enumeration<JarEntry> entries = jar.entries();
+ findClassesInPackageByJar(pack, entries, packageDirName, classes);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return classes;
+ }
+
+ private static void findClassesInPackageByFile(String packageName, String packagePath, Set<Class<?>> classes) {
+ File dir = new File(packagePath);
+
+ if (!dir.exists() || !dir.isDirectory()) {
+ return;
+ }
+
+ File[] dirfiles = dir.listFiles((file) -> file.isDirectory() || file.getName().endsWith(".class"));
+ if (dirfiles != null) {
+ for (File file : dirfiles) {
+ if (file.isDirectory()) {
+ findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), classes);
+ } else {
+ String className = file.getName().substring(0, file.getName().length() - 6);
+ try {
+ classes.add(Class.forName(packageName + '.' + className));
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ }
+
+ private static void findClassesInPackageByJar(String packageName, Enumeration<JarEntry> entries, String packageDirName, Set<Class<?>> classes) {
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ String name = entry.getName();
+ if (name.charAt(0) == '/') {
+ name = name.substring(1);
+ }
+ if (name.startsWith(packageDirName)) {
+ int idx = name.lastIndexOf('/');
+ if (idx != -1) {
+ packageName = name.substring(0, idx).replace('/', '.');
+ }
+ if (name.endsWith(".class") && !entry.isDirectory()) {
+ String className = name.substring(packageName.length() + 1, name.length() - 6);
+ try {
+ classes.add(Class.forName(packageName + '.' + className));
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/utils/NullPlugin.java b/src/main/java/me/earthme/luminol/utils/NullPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..de94c8e39f0ae0da80d5a79af63413e287f5d190
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/utils/NullPlugin.java
@@ -0,0 +1,152 @@
+package me.earthme.luminol.utils;
+
+import io.papermc.paper.plugin.configuration.PluginMeta;
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
+import org.bukkit.Server;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.generator.BiomeProvider;
+import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.plugin.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class NullPlugin extends PluginBase {
+ private boolean enabled = true;
+
+ private final String pluginName;
+ private PluginDescriptionFile pdf;
+
+ public NullPlugin() {
+ this.pluginName = "Minecraft";
+ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms");
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ public File getDataFolder() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public PluginDescriptionFile getDescription() {
+ return pdf;
+ }
+ // Paper start
+ @Override
+ public io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() {
+ return pdf;
+ }
+ // Paper end
+
+ @Override
+ public FileConfiguration getConfig() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public InputStream getResource(String filename) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void saveConfig() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void saveDefaultConfig() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void saveResource(String resourcePath, boolean replace) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void reloadConfig() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public PluginLogger getLogger() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public PluginLoader getPluginLoader() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public Server getServer() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @Override
+ public void onDisable() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void onLoad() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void onEnable() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public boolean isNaggable() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public void setNaggable(boolean canNag) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public @Nullable BiomeProvider getDefaultBiomeProvider(@NotNull String worldName, @Nullable String id) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ @Override
+ public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+
+ // Paper start - lifecycle events
+ @Override
+ public @NotNull io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager<org.bukkit.plugin.Plugin> getLifecycleManager() {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+ // Paper end - lifecycle events
+}
\ No newline at end of file

View File

@@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 29 Jan 2025 09:08:22 +0800
Date: Tue, 11 Feb 2025 12:00:30 +0800
Subject: [PATCH] Add config to disable async catchers
@@ -79,32 +79,6 @@ index c95769a4e64fabd7acdff6c5f6f349107e1cf5c0..4efa1c057ae6cfdea7889c372bd62dc1
final String ex = "Thread failed main thread check: " +
reason + ", context=" + getThreadContext() + ", 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
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/DisableAsyncCatcherConfig.java
@@ -0,0 +1,20 @@
+package me.earthme.luminol.config.modules.experiment;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class DisableAsyncCatcherConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.EXPERIMENT;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "disable_async_catchers";
+ }
+}
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
index 50f01faa88c8c658252fade3748f20e48e9c8432..36fa1f83c3286e10cc7c208a2a2f1a718d525ad8 100644
--- a/src/main/java/org/spigotmc/AsyncCatcher.java

View File

@@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 11 Feb 2025 11:57:22 +0800
Subject: [PATCH] Add tpsbar with chunkhot membar and region bar
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 2d1b672fc152054d7b6abf47f443b87f5a2ea3de..3e4e0dcdd4e2808aef8dd41f159a358f47450f40 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2404,6 +2404,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
handle.expToDrop = data.getInt("expToDrop");
handle.keepLevel = data.getBoolean("keepLevel");
}
+ //Luminol start - Tpsbar
+ getHandle().isTpsBarVisible = data.getBoolean("tpsbarVisible");
+ //Luminol end
+ //Luminol start - Membar
+ getHandle().isMemBarVisible = data.getBoolean("membarVisible");
+ //Luminol end
+ //Luminol start - Regionbar
+ getHandle().isRegionBarVisible = data.getBoolean("regionbarVisible");
+ //Luminol end
}
}
@@ -2425,6 +2434,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
data.putLong("lastPlayed", System.currentTimeMillis());
data.putString("lastKnownName", handle.getScoreboardName());
+ //Luminol start - Tpsbar
+ data.putBoolean("tpsbarVisible",handle.isTpsBarVisible);
+ //Luminol end
+ //Luminol start - Membar
+ data.putBoolean("membarVisible", handle.isMemBarVisible);
+ //Luminol end
+ //Luminol start - Regionbar
+ data.putBoolean("regionbarVisible", handle.isRegionBarVisible);
+ //Luminol end
// Paper start - persist for use in offline save data
if (!nbttagcompound.contains("Paper")) {
nbttagcompound.put("Paper", new CompoundTag());
@@ -3611,4 +3629,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return forwardMovement == backwardMovement ? 0 : forwardMovement ? 1 : -1;
}
+
+ // KioCG start - ChunkHot
+ @Override
+ public long getNearbyChunkHot() {
+ return this.getHandle().getNearbyChunkHot();
+ }
+ // KioCG end
}

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 11 Feb 2025 12:01:39 +0800
Subject: [PATCH] Purpur Lobotomize stuck villagers
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index bd515cdfbcc6fb0d17f70150d8b0bab60949db49..b6038fedea6251226b3b3db0f4b7a1f3d2276ab0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -381,4 +381,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
getHandle().getGossips().gossips.clear();
}
// Paper end
+
+ // Purpur start
+ @Override
+ public boolean isLobotomized() {
+ return getHandle().isLobotomized();
+ }
+ // Purpur end
}

View File

@@ -18,10 +18,10 @@ index a0b84535a9d3833d4df692b85b272f145559dd80..c2ba46408b5ad727d7a17f21d47b2898
return;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index bcd17eba9798747010ed96903992939a284199df..f9f20e9fd4530d0130046b56c55e798d4ede29d1 100644
index 09853a5035a6cb2f9efa20a68644038f11065a9d..00b3db1c0c449e77cd365c70d0ce044c56b2dcf7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -313,7 +313,7 @@ public final class CraftServer implements Server {
@@ -314,7 +314,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
@@ -30,7 +30,7 @@ index bcd17eba9798747010ed96903992939a284199df..f9f20e9fd4530d0130046b56c55e798d
// 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
@@ -491,7 +491,7 @@ public final class CraftServer implements Server {
@@ -492,7 +492,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
@@ -39,7 +39,7 @@ index bcd17eba9798747010ed96903992939a284199df..f9f20e9fd4530d0130046b56c55e798d
}
public boolean getCommandBlockOverride(String command) {
@@ -1155,7 +1155,7 @@ public final class CraftServer implements Server {
@@ -1156,7 +1156,7 @@ public final class CraftServer implements Server {
this.reloadData();
org.spigotmc.SpigotConfig.registerCommands(); // Spigot
io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper
@@ -48,7 +48,7 @@ index bcd17eba9798747010ed96903992939a284199df..f9f20e9fd4530d0130046b56c55e798d
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
@@ -1184,7 +1184,7 @@ public final class CraftServer implements Server {
@@ -1185,7 +1185,7 @@ public final class CraftServer implements Server {
this.loadPlugins();
this.enablePlugins(PluginLoadOrder.STARTUP);
this.enablePlugins(PluginLoadOrder.POSTWORLD);

View File

@@ -1,14 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 15:35:44 +0800
Date: Tue, 11 Feb 2025 11:46:26 +0800
Subject: [PATCH] SparklyPaper Optimize canSee checks
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 84304fc8c26a6e1e3515b131a2ee3357262efcc3..e3fe81a1d91f60c6696070751c5220ec1868390a 100644
index 3e4e0dcdd4e2808aef8dd41f159a358f47450f40..450350e66ae42f234bfd3016da1434e3194259e2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -213,7 +213,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -214,7 +214,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private boolean hasPlayedBefore = false;
private final ConversationTracker conversationTracker = new ConversationTracker();
private final Set<String> channels = new HashSet<String>();
@@ -17,7 +17,7 @@ index 84304fc8c26a6e1e3515b131a2ee3357262efcc3..e3fe81a1d91f60c6696070751c5220ec
private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
private int hash = 0;
@@ -2267,9 +2267,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2268,9 +2268,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public boolean canSee(org.bukkit.entity.Entity entity) {

View File

@@ -1,58 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
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";
+ }
+}

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 11 Feb 2025 12:03:38 +0800
Subject: [PATCH] Leaf Secure seed and matter seed command
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index f42692cd4f0154705c3d5b030d281cfc333803ed..39cc976f65f826a00e2e637c139f9134c5e74715 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -206,7 +206,12 @@ public class CraftChunk implements Chunk {
@Override
public boolean isSlimeChunk() {
// 987234911L is deterimined in EntitySlime when seeing if a slime can spawn in a chunk
- return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ // Leaf start - Matter - Secure Seed
+ boolean isSlimeChunk = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? worldServer.getChunk(this.getX(), this.getZ()).isSlimeChunk()
+ : WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
+ // Leaf end - Matter - Secure Seed
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 00b3db1c0c449e77cd365c70d0ce044c56b2dcf7..4e9248980ee7400d856dc30792197468559bfe9b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1423,7 +1423,11 @@ public final class CraftServer implements Server {
registryAccess = levelDataAndDimensions.dimensions().dimensionsRegistryAccess();
} else {
LevelSettings levelSettings;
- WorldOptions worldOptions = new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf start - Matter - Secure Seed
+ WorldOptions worldOptions = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new WorldOptions(creator.seed(), su.plo.matter.Globals.createRandomWorldSeed(), creator.generateStructures(), false)
+ : new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf end - Matter - Secure Seed
WorldDimensions worldDimensions;
DedicatedServerProperties.WorldDimensionData properties = new DedicatedServerProperties.WorldDimensionData(GsonHelper.parse((creator.generatorSettings().isEmpty()) ? "{}" : creator.generatorSettings()), creator.type().name().toLowerCase(Locale.ROOT));

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 11 Feb 2025 11:46:44 +0800
Subject: [PATCH] Tick regions api
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 82d26889661a944e057be0c450fb5a296122ea8e..4f320a91fb8abe21cbb7b01fdc34330def5b2448 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2517,4 +2517,11 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return this.adventure$pointers;
}
// Paper end
+
+ // Luminol start - Tick regions api
+ @Override
+ public me.earthme.luminol.api.ThreadedRegionizer getThreadedRegionizer() {
+ return new me.earthme.luminol.api.impl.ThreadedRegionizerImpl(this.world);
+ }
+ // Luminol end
}

View File

@@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
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";
+ }
+}

View File

@@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Suisuroru <qwertyuiop14077@qq.com>
Date: Thu, 20 Feb 2025 01:00:29 +0800
Subject: [PATCH] Purpur-Barrels-and-enderchests-6-rows
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
index 1ce328bed5cf3d087a3f7dc9236153381d758493..20f2b9945eaa58e05b417d9cca7c30dd0496cf72 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
@@ -145,9 +145,26 @@ public class CraftContainer extends AbstractContainerMenu {
case PLAYER:
case CHEST:
case ENDER_CHEST:
- case BARREL:
- this.delegate = new ChestMenu(net.minecraft.world.inventory.MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9);
+ // Purpur start - Barrels and enderchests 6 rows
+ this.delegate = new ChestMenu(switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.enderchestRows) {
+ case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6;
+ case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5;
+ case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4;
+ case 2 -> net.minecraft.world.inventory.MenuType.GENERIC_9x2;
+ case 1 -> net.minecraft.world.inventory.MenuType.GENERIC_9x1;
+ default -> net.minecraft.world.inventory.MenuType.GENERIC_9x3;
+ }, windowId, bottom, top, top.getContainerSize() / 9);
break;
+ case BARREL:
+ this.delegate = new ChestMenu(switch (me.earthme.luminol.config.modules.misc.ContainerExpansionConfig.barrelRows) {
+ case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6;
+ case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5;
+ case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4;
+ case 2 -> net.minecraft.world.inventory.MenuType.GENERIC_9x2;
+ case 1 -> net.minecraft.world.inventory.MenuType.GENERIC_9x1;
+ default -> net.minecraft.world.inventory.MenuType.GENERIC_9x3;
+ }, windowId, bottom, top, top.getContainerSize() / 9);
+ // Purpur end - Barrels and enderchests 6 rows
case DISPENSER:
case DROPPER:
this.delegate = new DispenserMenu(windowId, bottom, top);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
index c6159c70f7a37b9bffe268b91905ce848d1d2927..1ae08daecb7f072e0afaae327bad64e43c3ae027 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
@@ -84,7 +84,7 @@ public class CraftInventory implements Inventory {
@Override
public void setContents(ItemStack[] items) {
- Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize());
+ // Preconditions.checkArgument(items.length <= this.getSize(), "Invalid inventory size (%s); expected %s or less", items.length, this.getSize()); // Purpur - Barrels and enderchests 6 rows
for (int i = 0; i < this.getSize(); i++) {
if (i >= items.length) {

View File

@@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 29 Jan 2025 14:57:27 +0800
Subject: [PATCH] Skip collision check if the block is not belong to current
tick region
A temporary fix of these issues:
https://github.com/PaperMC/Folia/issues/311
Due to that mojang won't ignore the blocks the entity passed by, and sometimes the old position may not be updated and it points to a block that we don't own it, and it will access it during applyEffectsFromBlocks.So the best way to fix that is to skip the collision check of that block because it was already not owned by us and it's not necessary to check it
Related to mojang's bug fix:
https://bugs.mojang.com/browse/MC-92875
diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaOldPositionIssueFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaOldPositionIssueFixConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..7294792d934e7374dcf335135dda739702fdcc62
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaOldPositionIssueFixConfig.java
@@ -0,0 +1,20 @@
+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 FoliaOldPositionIssueFixConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.FIXES;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "folia.fix_old_position_issue";
+ }
+}

View File

@@ -1,201 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 29 Jan 2025 09:12:07 +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 = "<gray>TPS<yellow>:</yellow> <tps> MSPT<yellow>:</yellow> <mspt> Ping<yellow>:</yellow> <ping>ms";
+ public static String tpsBarFormat = "<gray>TPS<yellow>:</yellow> <tps> MSPT<yellow>:</yellow> <mspt> Ping<yellow>:</yellow> <ping>ms ChunkHot<yellow>:</yellow> <chunkhot>";
@ConfigInfo(baseName = "tps_color_list")
public static List<String> tpsColors = List.of("GREEN","YELLOW","RED","PURPLE");
@ConfigInfo(baseName = "ping_color_list")
public static List<String> pingColors = List.of("GREEN","YELLOW","RED","PURPLE");
+ @ConfigInfo(baseName = "chunkhot_color_list")
+ public static List<String> 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><text></%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 03a9f4d8e83f53326c30f00286efd1ddaaac84d2..84304fc8c26a6e1e3515b131a2ee3357262efcc3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3611,4 +3611,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
handle.containerMenu.broadcastChanges();
return new PaperPlayerGiveResult(leftovers.build(), drops.build());
}
+
+ // KioCG start - ChunkHot
+ @Override
+ public long getNearbyChunkHot() {
+ return this.getHandle().getNearbyChunkHot();
+ }
+ // KioCG end
}

View File

@@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Thu, 30 Jan 2025 08:42:31 +0800
Subject: [PATCH] Purpur Lobotomize stuck villagers
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/LobotomizeVillageConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/LobotomizeVillageConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b30546a26634361cd6eb2dbf08af9e2608a060f
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/LobotomizeVillageConfig.java
@@ -0,0 +1,24 @@
+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 LobotomizeVillageConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean villagerLobotomizeEnabled = false;
+ @ConfigInfo(baseName = "check_interval")
+ public static int villagerLobotomizeCheckInterval = 100;
+ @ConfigInfo(baseName = "wait_until_trade_locked")
+ public static boolean villagerLobotomizeWaitUntilTradeLocked = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.OPTIMIZATIONS;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "lobotomize_villager";
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index bd515cdfbcc6fb0d17f70150d8b0bab60949db49..b6038fedea6251226b3b3db0f4b7a1f3d2276ab0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -381,4 +381,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
getHandle().getGossips().gossips.clear();
}
// Paper end
+
+ // Purpur start
+ @Override
+ public boolean isLobotomized() {
+ return getHandle().isLobotomized();
+ }
+ // Purpur end
}

View File

@@ -1,413 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 28 Jan 2025 18:56:59 +0800
Subject: [PATCH] Leaf Secure seed and matter seed command
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..923e6dee55b765e46737ee145c32b767558c0132
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java
@@ -0,0 +1,22 @@
+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 SecureSeedConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled", comments = """
+ Once you enable secure seed, all ores and structures are generated with 1024-bit seed
+ instead of using 64-bit seed in vanilla, made seed cracker become impossible.""")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "secure_seed";
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index f42692cd4f0154705c3d5b030d281cfc333803ed..39cc976f65f826a00e2e637c139f9134c5e74715 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -206,7 +206,12 @@ public class CraftChunk implements Chunk {
@Override
public boolean isSlimeChunk() {
// 987234911L is deterimined in EntitySlime when seeing if a slime can spawn in a chunk
- return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ // Leaf start - Matter - Secure Seed
+ boolean isSlimeChunk = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? worldServer.getChunk(this.getX(), this.getZ()).isSlimeChunk()
+ : WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
+ // Leaf end - Matter - Secure Seed
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index f9f20e9fd4530d0130046b56c55e798d4ede29d1..d34502a826b1582dd13c6983ed1060373837353f 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1422,7 +1422,11 @@ public final class CraftServer implements Server {
registryAccess = levelDataAndDimensions.dimensions().dimensionsRegistryAccess();
} else {
LevelSettings levelSettings;
- WorldOptions worldOptions = new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf start - Matter - Secure Seed
+ WorldOptions worldOptions = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new WorldOptions(creator.seed(), su.plo.matter.Globals.createRandomWorldSeed(), creator.generateStructures(), false)
+ : new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf end - Matter - Secure Seed
WorldDimensions worldDimensions;
DedicatedServerProperties.WorldDimensionData properties = new DedicatedServerProperties.WorldDimensionData(GsonHelper.parse((creator.generatorSettings().isEmpty()) ? "{}" : creator.generatorSettings()), creator.type().name().toLowerCase(Locale.ROOT));
diff --git a/src/main/java/su/plo/matter/Globals.java b/src/main/java/su/plo/matter/Globals.java
new file mode 100644
index 0000000000000000000000000000000000000000..3cb89c197ca82c7f86c821fd96f6342428fff5d3
--- /dev/null
+++ b/src/main/java/su/plo/matter/Globals.java
@@ -0,0 +1,94 @@
+package su.plo.matter;
+
+import com.google.common.collect.Iterables;
+import net.minecraft.server.level.ServerLevel;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Optional;
+
+public class Globals {
+ public static final int WORLD_SEED_LONGS = 16;
+ public static final int WORLD_SEED_BITS = WORLD_SEED_LONGS * 64;
+
+ public static final long[] worldSeed = new long[WORLD_SEED_LONGS];
+ public static final ThreadLocal<Integer> dimension = ThreadLocal.withInitial(() -> 0);
+
+ public enum Salt {
+ UNDEFINED,
+ BASTION_FEATURE,
+ WOODLAND_MANSION_FEATURE,
+ MINESHAFT_FEATURE,
+ BURIED_TREASURE_FEATURE,
+ NETHER_FORTRESS_FEATURE,
+ PILLAGER_OUTPOST_FEATURE,
+ GEODE_FEATURE,
+ NETHER_FOSSIL_FEATURE,
+ OCEAN_MONUMENT_FEATURE,
+ RUINED_PORTAL_FEATURE,
+ POTENTIONAL_FEATURE,
+ GENERATE_FEATURE,
+ JIGSAW_PLACEMENT,
+ STRONGHOLDS,
+ POPULATION,
+ DECORATION,
+ SLIME_CHUNK
+ }
+
+ public static void setupGlobals(ServerLevel world) {
+ if (!me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) return;
+
+ long[] seed = world.getServer().getWorldData().worldGenOptions().featureSeed();
+ System.arraycopy(seed, 0, worldSeed, 0, WORLD_SEED_LONGS);
+ int worldIndex = Iterables.indexOf(world.getServer().levelKeys(), it -> it == world.dimension());
+ if (worldIndex == -1)
+ worldIndex = world.getServer().levelKeys().size(); // if we are in world construction it may not have been added to the map yet
+ dimension.set(worldIndex);
+ }
+
+ public static long[] createRandomWorldSeed() {
+ long[] seed = new long[WORLD_SEED_LONGS];
+ SecureRandom rand = new SecureRandom();
+ for (int i = 0; i < WORLD_SEED_LONGS; i++) {
+ seed[i] = rand.nextLong();
+ }
+ return seed;
+ }
+
+ // 1024-bit string -> 16 * 64 long[]
+ public static Optional<long[]> parseSeed(String seedStr) {
+ if (seedStr.isEmpty()) return Optional.empty();
+
+ if (seedStr.length() != WORLD_SEED_BITS) {
+ throw new IllegalArgumentException("Secure seed length must be " + WORLD_SEED_BITS + "-bit but found " + seedStr.length() + "-bit.");
+ }
+
+ long[] seed = new long[WORLD_SEED_LONGS];
+
+ for (int i = 0; i < WORLD_SEED_LONGS; i++) {
+ int start = i * 64;
+ int end = start + 64;
+ String seedSection = seedStr.substring(start, end);
+
+ BigInteger seedInDecimal = new BigInteger(seedSection, 2);
+ seed[i] = seedInDecimal.longValue();
+ }
+
+ return Optional.of(seed);
+ }
+
+ // 16 * 64 long[] -> 1024-bit string
+ public static String seedToString(long[] seed) {
+ StringBuilder sb = new StringBuilder();
+
+ for (long longV : seed) {
+ // Convert to 64-bit binary string per long
+ // Use format to keep 64-bit length, and use 0 to complete space
+ String binaryStr = String.format("%64s", Long.toBinaryString(longV)).replace(' ', '0');
+
+ sb.append(binaryStr);
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/su/plo/matter/Hashing.java b/src/main/java/su/plo/matter/Hashing.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec7a57c6af5d5f4fd27a643d253c2ecce90c01ac
--- /dev/null
+++ b/src/main/java/su/plo/matter/Hashing.java
@@ -0,0 +1,73 @@
+package su.plo.matter;
+
+public class Hashing {
+ // https://en.wikipedia.org/wiki/BLAKE_(hash_function)
+ // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/digests/Blake2bDigest.java
+
+ private final static long[] blake2b_IV = {
+ 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL,
+ 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL,
+ 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L
+ };
+
+ private final static byte[][] blake2b_sigma = {
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+ {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
+ {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
+ {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
+ {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
+ {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
+ {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
+ {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
+ {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}
+ };
+
+ public static long[] hashWorldSeed(long[] worldSeed) {
+ long[] result = blake2b_IV.clone();
+ result[0] ^= 0x01010040;
+ hash(worldSeed, result, new long[16], 0, false);
+ return result;
+ }
+
+ public static void hash(long[] message, long[] chainValue, long[] internalState, long messageOffset, boolean isFinal) {
+ assert message.length == 16;
+ assert chainValue.length == 8;
+ assert internalState.length == 16;
+
+ System.arraycopy(chainValue, 0, internalState, 0, chainValue.length);
+ System.arraycopy(blake2b_IV, 0, internalState, chainValue.length, 4);
+ internalState[12] = messageOffset ^ blake2b_IV[4];
+ internalState[13] = blake2b_IV[5];
+ if (isFinal) internalState[14] = ~blake2b_IV[6];
+ internalState[15] = blake2b_IV[7];
+
+ for (int round = 0; round < 12; round++) {
+ G(message[blake2b_sigma[round][0]], message[blake2b_sigma[round][1]], 0, 4, 8, 12, internalState);
+ G(message[blake2b_sigma[round][2]], message[blake2b_sigma[round][3]], 1, 5, 9, 13, internalState);
+ G(message[blake2b_sigma[round][4]], message[blake2b_sigma[round][5]], 2, 6, 10, 14, internalState);
+ G(message[blake2b_sigma[round][6]], message[blake2b_sigma[round][7]], 3, 7, 11, 15, internalState);
+ G(message[blake2b_sigma[round][8]], message[blake2b_sigma[round][9]], 0, 5, 10, 15, internalState);
+ G(message[blake2b_sigma[round][10]], message[blake2b_sigma[round][11]], 1, 6, 11, 12, internalState);
+ G(message[blake2b_sigma[round][12]], message[blake2b_sigma[round][13]], 2, 7, 8, 13, internalState);
+ G(message[blake2b_sigma[round][14]], message[blake2b_sigma[round][15]], 3, 4, 9, 14, internalState);
+ }
+
+ for (int i = 0; i < 8; i++) {
+ chainValue[i] ^= internalState[i] ^ internalState[i + 8];
+ }
+ }
+
+ private static void G(long m1, long m2, int posA, int posB, int posC, int posD, long[] internalState) {
+ internalState[posA] = internalState[posA] + internalState[posB] + m1;
+ internalState[posD] = Long.rotateRight(internalState[posD] ^ internalState[posA], 32);
+ internalState[posC] = internalState[posC] + internalState[posD];
+ internalState[posB] = Long.rotateRight(internalState[posB] ^ internalState[posC], 24); // replaces 25 of BLAKE
+ internalState[posA] = internalState[posA] + internalState[posB] + m2;
+ internalState[posD] = Long.rotateRight(internalState[posD] ^ internalState[posA], 16);
+ internalState[posC] = internalState[posC] + internalState[posD];
+ internalState[posB] = Long.rotateRight(internalState[posB] ^ internalState[posC], 63); // replaces 11 of BLAKE
+ }
+}
diff --git a/src/main/java/su/plo/matter/WorldgenCryptoRandom.java b/src/main/java/su/plo/matter/WorldgenCryptoRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..fab359afe44c573b8b315115810ddefd85b4d22b
--- /dev/null
+++ b/src/main/java/su/plo/matter/WorldgenCryptoRandom.java
@@ -0,0 +1,159 @@
+package su.plo.matter;
+
+import net.minecraft.util.Mth;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.levelgen.LegacyRandomSource;
+import net.minecraft.world.level.levelgen.WorldgenRandom;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+public class WorldgenCryptoRandom extends WorldgenRandom {
+ // hash the world seed to guard against badly chosen world seeds
+ private static final long[] HASHED_ZERO_SEED = Hashing.hashWorldSeed(new long[Globals.WORLD_SEED_LONGS]);
+ private static final ThreadLocal<long[]> LAST_SEEN_WORLD_SEED = ThreadLocal.withInitial(() -> new long[Globals.WORLD_SEED_LONGS]);
+ private static final ThreadLocal<long[]> HASHED_WORLD_SEED = ThreadLocal.withInitial(() -> HASHED_ZERO_SEED);
+
+ private final long[] worldSeed = new long[Globals.WORLD_SEED_LONGS];
+ private final long[] randomBits = new long[8];
+ private int randomBitIndex;
+ private static final int MAX_RANDOM_BIT_INDEX = 64 * 8;
+ private static final int LOG2_MAX_RANDOM_BIT_INDEX = 9;
+ private long counter;
+ private final long[] message = new long[16];
+ private final long[] cachedInternalState = new long[16];
+
+ public WorldgenCryptoRandom(int x, int z, Globals.Salt typeSalt, long salt) {
+ super(new LegacyRandomSource(0L));
+ if (typeSalt != null) {
+ this.setSecureSeed(x, z, typeSalt, salt);
+ }
+ }
+
+ public void setSecureSeed(int x, int z, Globals.Salt typeSalt, long salt) {
+ System.arraycopy(Globals.worldSeed, 0, this.worldSeed, 0, Globals.WORLD_SEED_LONGS);
+ message[0] = ((long) x << 32) | ((long) z & 0xffffffffL);
+ message[1] = ((long) Globals.dimension.get() << 32) | ((long) salt & 0xffffffffL);
+ message[2] = typeSalt.ordinal();
+ message[3] = counter = 0;
+ randomBitIndex = MAX_RANDOM_BIT_INDEX;
+ }
+
+ private long[] getHashedWorldSeed() {
+ if (!Arrays.equals(worldSeed, LAST_SEEN_WORLD_SEED.get())) {
+ HASHED_WORLD_SEED.set(Hashing.hashWorldSeed(worldSeed));
+ System.arraycopy(worldSeed, 0, LAST_SEEN_WORLD_SEED.get(), 0, Globals.WORLD_SEED_LONGS);
+ }
+ return HASHED_WORLD_SEED.get();
+ }
+
+ private void moreRandomBits() {
+ message[3] = counter++;
+ System.arraycopy(getHashedWorldSeed(), 0, randomBits, 0, 8);
+ Hashing.hash(message, randomBits, cachedInternalState, 64, true);
+ }
+
+ private long getBits(int count) {
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX) {
+ moreRandomBits();
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ }
+
+ int alignment = randomBitIndex & 63;
+ if ((randomBitIndex >>> 6) == ((randomBitIndex + count) >>> 6)) {
+ long result = (randomBits[randomBitIndex >>> 6] >>> alignment) & ((1L << count) - 1);
+ randomBitIndex += count;
+ return result;
+ } else {
+ long result = (randomBits[randomBitIndex >>> 6] >>> alignment) & ((1L << (64 - alignment)) - 1);
+ randomBitIndex += count;
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX) {
+ moreRandomBits();
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ }
+ alignment = randomBitIndex & 63;
+ result <<= alignment;
+ result |= (randomBits[randomBitIndex >>> 6] >>> (64 - alignment)) & ((1L << alignment) - 1);
+
+ return result;
+ }
+ }
+
+ @Override
+ public @NotNull RandomSource fork() {
+ WorldgenCryptoRandom fork = new WorldgenCryptoRandom(0, 0, null, 0);
+
+ System.arraycopy(Globals.worldSeed, 0, fork.worldSeed, 0, Globals.WORLD_SEED_LONGS);
+ fork.message[0] = this.message[0];
+ fork.message[1] = this.message[1];
+ fork.message[2] = this.message[2];
+ fork.message[3] = this.message[3];
+ fork.randomBitIndex = this.randomBitIndex;
+ fork.counter = this.counter;
+ fork.nextLong();
+
+ return fork;
+ }
+
+ @Override
+ public int next(int bits) {
+ return (int) getBits(bits);
+ }
+
+ @Override
+ public void consumeCount(int count) {
+ randomBitIndex += count;
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX * 2) {
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ counter += randomBitIndex >>> LOG2_MAX_RANDOM_BIT_INDEX;
+ randomBitIndex &= MAX_RANDOM_BIT_INDEX - 1;
+ randomBitIndex += MAX_RANDOM_BIT_INDEX;
+ }
+ }
+
+ @Override
+ public int nextInt(int bound) {
+ int bits = Mth.ceillog2(bound);
+ int result;
+ do {
+ result = (int) getBits(bits);
+ } while (result >= bound);
+
+ return result;
+ }
+
+ @Override
+ public long nextLong() {
+ return getBits(64);
+ }
+
+ @Override
+ public double nextDouble() {
+ return getBits(53) * 0x1.0p-53;
+ }
+
+ @Override
+ public long setDecorationSeed(long worldSeed, int blockX, int blockZ) {
+ setSecureSeed(blockX, blockZ, Globals.Salt.POPULATION, 0);
+ return ((long) blockX << 32) | ((long) blockZ & 0xffffffffL);
+ }
+
+ @Override
+ public void setFeatureSeed(long populationSeed, int index, int step) {
+ setSecureSeed((int) (populationSeed >> 32), (int) populationSeed, Globals.Salt.DECORATION, index + 10000L * step);
+ }
+
+ @Override
+ public void setLargeFeatureSeed(long worldSeed, int chunkX, int chunkZ) {
+ super.setLargeFeatureSeed(worldSeed, chunkX, chunkZ);
+ }
+
+ @Override
+ public void setLargeFeatureWithSalt(long worldSeed, int regionX, int regionZ, int salt) {
+ super.setLargeFeatureWithSalt(worldSeed, regionX, regionZ, salt);
+ }
+
+ public static RandomSource seedSlimeChunk(int chunkX, int chunkZ) {
+ return new WorldgenCryptoRandom(chunkX, chunkZ, Globals.Salt.SLIME_CHUNK, 0);
+ }
+}

View File

@@ -1,203 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Mon, 27 Jan 2025 13:01:56 +0800
Subject: [PATCH] Tick regions api
diff --git a/src/main/java/me/earthme/luminol/api/impl/RegionStatsImpl.java b/src/main/java/me/earthme/luminol/api/impl/RegionStatsImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..30d4e7b6a433974c5047148f35973eb31c82d424
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/RegionStatsImpl.java
@@ -0,0 +1,27 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.RegionStats;
+
+public class RegionStatsImpl implements RegionStats {
+ private final TickRegions.RegionStats internal;
+
+ public RegionStatsImpl(TickRegions.RegionStats internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public int getEntityCount() {
+ return this.internal.getEntityCount();
+ }
+
+ @Override
+ public int getPlayerCount() {
+ return this.internal.getPlayerCount();
+ }
+
+ @Override
+ public int getChunkCount() {
+ return this.internal.getChunkCount();
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionImpl.java b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1380abacf7bc0fe106982d9b4cd7bbc44e4e375
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionImpl.java
@@ -0,0 +1,47 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.ThreadedRegionizer;
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.ThreadedRegion;
+import me.earthme.luminol.api.TickRegionData;
+import net.minecraft.world.level.ChunkPos;
+import org.bukkit.Location;
+import org.bukkit.World;
+
+import javax.annotation.Nullable;
+
+public class ThreadedRegionImpl implements ThreadedRegion {
+ private final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> internal;
+
+ public ThreadedRegionImpl(ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> internal) {
+ this.internal = internal;
+ }
+
+ @Nullable
+ @Override
+ public Location getCenterChunkPos() {
+ final ChunkPos centerChunkPos = this.internal.getCenterChunk();
+
+ if (centerChunkPos == null) {
+ return null;
+ }
+
+ return new Location(this.internal.regioniser.world.getWorld(), centerChunkPos.getMiddleBlockX(), 0, centerChunkPos.getMiddleBlockZ());
+ }
+
+ @Override
+ public double getDeadSectionPercent() {
+ return this.internal.getDeadSectionPercent();
+ }
+
+ @Override
+ public TickRegionData getTickRegionData() {
+ return new TickRegionDataImpl(this.internal.getData());
+ }
+
+ @Nullable
+ @Override
+ public World getWorld() {
+ return this.internal.regioniser.world.getWorld();
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionizerImpl.java b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionizerImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..203ba60216febd8c19315afd89140d5400213f67
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionizerImpl.java
@@ -0,0 +1,53 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.ThreadedRegion;
+import me.earthme.luminol.api.ThreadedRegionizer;
+import net.minecraft.server.level.ServerLevel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ThreadedRegionizerImpl implements ThreadedRegionizer {
+ private final ServerLevel internal;
+
+ public ThreadedRegionizerImpl(ServerLevel internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public Collection<ThreadedRegion> getAllRegions() {
+ final List<ThreadedRegion> ret = new ArrayList<>();
+
+ this.internal.regioniser.computeForAllRegions(region -> {
+ final ThreadedRegion wrapped = new ThreadedRegionImpl(region);
+
+ ret.add(wrapped);
+ });
+
+ return ret;
+ }
+
+ @Override
+ public ThreadedRegion getAtSynchronized(int chunkX, int chunkZ) {
+ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> got = this.internal.regioniser.getRegionAtSynchronised(chunkX, chunkZ);
+
+ if (got == null) {
+ return null;
+ }
+
+ return new ThreadedRegionImpl(got);
+ }
+
+ @Override
+ public ThreadedRegion getAtUnSynchronized(int chunkX, int chunkZ) {
+ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> got = this.internal.regioniser.getRegionAtUnsynchronised(chunkX, chunkZ);
+
+ if (got == null) {
+ return null;
+ }
+
+ return new ThreadedRegionImpl(got);
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/api/impl/TickRegionDataImpl.java b/src/main/java/me/earthme/luminol/api/impl/TickRegionDataImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf51350ccabeda97e9eff41ccd30c58e836fe041
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/TickRegionDataImpl.java
@@ -0,0 +1,30 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.RegionStats;
+import me.earthme.luminol.api.TickRegionData;
+import org.bukkit.World;
+
+public class TickRegionDataImpl implements TickRegionData {
+ private final TickRegions.TickRegionData internal;
+
+ public TickRegionDataImpl(TickRegions.TickRegionData internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public World getWorld() {
+ return this.internal.world.getWorld();
+ }
+
+ @Override
+ public long getCurrentTickCount() {
+ return this.internal.getCurrentTick();
+ }
+
+ @Override
+ public RegionStats getRegionStats() {
+ return new RegionStatsImpl(this.internal.getRegionStats());
+ }
+
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index d7973737809177b577ce029d146325194eb0831e..57944f3f12417e5727b47caad3e9d03b4720b298 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2544,4 +2544,11 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return this.adventure$pointers;
}
// Paper end
+
+ // Luminol start - Tick regions api
+ @Override
+ public me.earthme.luminol.api.ThreadedRegionizer getThreadedRegionizer() {
+ return new me.earthme.luminol.api.impl.ThreadedRegionizerImpl(this.world);
+ }
+ // Luminol end
}

View File

@@ -0,0 +1,42 @@
--- /dev/null
+++ b/src/main/java/abomination/IRegionFile.java
@@ -1,0 +_,39 @@
+package abomination;
+
+import ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.level.ChunkPos;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+
+public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable {
+ Path getPath();
+
+ DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
+
+ boolean doesChunkExist(ChunkPos pos) throws Exception;
+
+ DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException;
+
+ void flush() throws IOException;
+
+ void clear(ChunkPos pos) throws IOException;
+
+ boolean hasChunk(ChunkPos pos);
+
+ void close() throws IOException;
+
+ void write(ChunkPos pos, ByteBuffer buf) throws IOException;
+
+ CompoundTag getOversizedData(int x, int z) throws IOException;
+
+ boolean isOversized(int x, int z);
+
+ boolean recalculateHeader() throws IOException;
+
+ void setOversized(int x, int z, boolean oversized) throws IOException;
+}

View File

@@ -1,61 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:49:22 +0800
Subject: [PATCH] Add configurable region format framework & linear v2 region
format support
diff --git a/src/main/java/abomination/IRegionFile.java b/src/main/java/abomination/IRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..fda43a34c89d75e3036f14da3c6efcf157189b22
--- /dev/null
+++ b/src/main/java/abomination/IRegionFile.java
@@ -0,0 +1,39 @@
+package abomination;
+
+import ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.level.ChunkPos;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+
+public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable {
+ Path getPath();
+
+ DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
+
+ boolean doesChunkExist(ChunkPos pos) throws Exception;
+
+ DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException;
+
+ void flush() throws IOException;
+
+ void clear(ChunkPos pos) throws IOException;
+
+ boolean hasChunk(ChunkPos pos);
+
+ void close() throws IOException;
+
+ void write(ChunkPos pos, ByteBuffer buf) throws IOException;
+
+ CompoundTag getOversizedData(int x, int z) throws IOException;
+
+ boolean isOversized(int x, int z);
+
+ boolean recalculateHeader() throws IOException;
+
+ void setOversized(int x, int z, boolean oversized) throws IOException;
+}
diff --git a/src/main/java/abomination/LinearRegionFile.java b/src/main/java/abomination/LinearRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb0fcf5f47b5ae3d86e1d0572f951236afdcd017
--- /dev/null
+++ b/src/main/java/abomination/LinearRegionFile.java
@@ -0,0 +1,622 @@
@@ -1,0 +_,622 @@
+package abomination;
+
+import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
@@ -678,142 +623,3 @@ index 0000000000000000000000000000000000000000..bb0fcf5f47b5ae3d86e1d0572f951236
+ }
+ }
+}
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
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
@@ -0,0 +1,59 @@
+package me.earthme.luminol.config.modules.misc;
+
+import abomination.LinearRegionFile;
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import me.earthme.luminol.config.*;
+import me.earthme.luminol.utils.EnumRegionFormat;
+import net.minecraft.server.MinecraftServer;
+
+public class RegionFormatConfig implements IConfigModule {
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "format")
+ public static String format = "MCA";
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_compression_level")
+ public static int linearCompressionLevel = 1;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_io_thread_count")
+ public static int linearIoThreadCount = 6;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_io_flush_delay_ms")
+ public static int linearIoFlushDelayMs = 100;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_use_virtual_thread")
+ public static boolean linearUseVirtualThread = true;
+
+ @DoNotLoad
+ public static EnumRegionFormat regionFormat;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "region_format";
+ }
+
+ @Override
+ public void onLoaded(CommentedFileConfig configInstance) {
+ regionFormat = EnumRegionFormat.fromString(format.toUpperCase());
+
+ if (regionFormat == null) {
+ throw new RuntimeException("Invalid region format: " + format);
+ }
+
+ if (regionFormat == EnumRegionFormat.LINEAR_V2) {
+ if (RegionFormatConfig.linearCompressionLevel > 23 || RegionFormatConfig.linearCompressionLevel < 1) {
+ MinecraftServer.LOGGER.error("Linear region compression level should be between 1 and 22 in config: {}", RegionFormatConfig.linearCompressionLevel);
+ MinecraftServer.LOGGER.error("Falling back to compression level 1.");
+ RegionFormatConfig.linearCompressionLevel = 1;
+ }
+
+ LinearRegionFile.SAVE_DELAY_MS = linearIoFlushDelayMs;
+ LinearRegionFile.SAVE_THREAD_MAX_COUNT = linearIoThreadCount;
+ LinearRegionFile.USE_VIRTUAL_THREAD = linearUseVirtualThread;
+ }
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/utils/EnumRegionFormat.java b/src/main/java/me/earthme/luminol/utils/EnumRegionFormat.java
new file mode 100644
index 0000000000000000000000000000000000000000..73b4f9b5f608322839cf1e37fbf1d3a147247c60
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/utils/EnumRegionFormat.java
@@ -0,0 +1,40 @@
+package me.earthme.luminol.utils;
+
+import abomination.LinearRegionFile;
+import me.earthme.luminol.config.modules.misc.RegionFormatConfig;
+import net.minecraft.world.level.chunk.storage.RegionFile;
+import org.jetbrains.annotations.Nullable;
+
+public enum EnumRegionFormat {
+ MCA("mca", "mca" , (info) -> new RegionFile(info.info(), info.filePath(), info.folder(), info.sync())),
+ LINEAR_V2("linear_v2", "linear" ,(info) -> new LinearRegionFile(info.info(), info.filePath(), info.folder(), info.sync(), RegionFormatConfig.linearCompressionLevel));
+
+ private final String name;
+ private final String argument;
+ private final IRegionCreateFunction creator;
+
+ EnumRegionFormat(String name, String argument, IRegionCreateFunction creator) {
+ this.name = name;
+ this.argument = argument;
+ this.creator = creator;
+ }
+
+ @Nullable
+ public static EnumRegionFormat fromString(String string) {
+ for (EnumRegionFormat format : values()) {
+ if (format.name.equalsIgnoreCase(string)) {
+ return format;
+ }
+ }
+
+ return null;
+ }
+
+ public IRegionCreateFunction getCreator() {
+ return this.creator;
+ }
+
+ public String getArgument() {
+ return this.argument;
+ }
+}
diff --git a/src/main/java/me/earthme/luminol/utils/IRegionCreateFunction.java b/src/main/java/me/earthme/luminol/utils/IRegionCreateFunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb87ef13803122aa5a2e7f0c578de359140d4f31
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/utils/IRegionCreateFunction.java
@@ -0,0 +1,9 @@
+package me.earthme.luminol.utils;
+
+import abomination.IRegionFile;
+
+import java.io.IOException;
+
+public interface IRegionCreateFunction {
+ IRegionFile create(RegionCreatorInfo info) throws IOException;
+}
diff --git a/src/main/java/me/earthme/luminol/utils/RegionCreatorInfo.java b/src/main/java/me/earthme/luminol/utils/RegionCreatorInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..5af068489646ed70330d8c6242ec88f536c4c289
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/utils/RegionCreatorInfo.java
@@ -0,0 +1,7 @@
+package me.earthme.luminol.utils;
+
+import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
+
+import java.nio.file.Path;
+
+public record RegionCreatorInfo (RegionStorageInfo info, Path filePath, Path folder, boolean sync) {}

View File

@@ -0,0 +1,93 @@
--- /dev/null
+++ b/src/main/java/com/kiocg/ChunkHot.java
@@ -1,0 +_,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);
+ }
+}

View File

@@ -0,0 +1,37 @@
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java
@@ -1,0 +_,34 @@
+package com.logisticscraft.occlusionculling;
+
+import com.logisticscraft.occlusionculling.util.Vec3d;
+
+public interface DataProvider {
+
+ /**
+ * Prepares the requested chunk. Returns true if the chunk is ready, false when
+ * not loaded. Should not reload the chunk when the x and y are the same as the
+ * last request!
+ *
+ * @param chunkX
+ * @param chunkZ
+ * @return
+ */
+ boolean prepareChunk(int chunkX, int chunkZ);
+
+ /**
+ * Location is inside the chunk.
+ *
+ * @param x
+ * @param y
+ * @param z
+ * @return
+ */
+ boolean isOpaqueFullCube(int x, int y, int z);
+
+ default void cleanup() {
+ }
+
+ default void checkingPosition(Vec3d[] targetPoints, int size, Vec3d viewerPosition) {
+ }
+
+}

View File

@@ -1,57 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 5 Feb 2025 15:22:21 +0800
Subject: [PATCH] Raytracing tracker experiment
Based on the framework of EntityCulling(((((((
diff --git a/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java b/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ab4600554e8dcb2a2ddc22dd1c1015c89ba5b82
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java
@@ -0,0 +1,34 @@
+package com.logisticscraft.occlusionculling;
+
+import com.logisticscraft.occlusionculling.util.Vec3d;
+
+public interface DataProvider {
+
+ /**
+ * Prepares the requested chunk. Returns true if the chunk is ready, false when
+ * not loaded. Should not reload the chunk when the x and y are the same as the
+ * last request!
+ *
+ * @param chunkX
+ * @param chunkZ
+ * @return
+ */
+ boolean prepareChunk(int chunkX, int chunkZ);
+
+ /**
+ * Location is inside the chunk.
+ *
+ * @param x
+ * @param y
+ * @param z
+ * @return
+ */
+ boolean isOpaqueFullCube(int x, int y, int z);
+
+ default void cleanup() {
+ }
+
+ default void checkingPosition(Vec3d[] targetPoints, int size, Vec3d viewerPosition) {
+ }
+
+}
diff --git a/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java b/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java
new file mode 100644
index 0000000000000000000000000000000000000000..30efa77d8ed337e9f044c41a10c6ecfd5ec162e2
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java
@@ -0,0 +1,515 @@
@@ -1,0 +_,515 @@
+package com.logisticscraft.occlusionculling;
+
+import java.util.Arrays;
@@ -567,477 +516,3 @@ index 0000000000000000000000000000000000000000..30efa77d8ed337e9f044c41a10c6ecfd
+ }
+
+}
diff --git a/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java b/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..08f0ddb343c12ac781ee33f1a7da1462573405b9
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java
@@ -0,0 +1,57 @@
+package com.logisticscraft.occlusionculling.cache;
+
+import java.util.Arrays;
+
+public class ArrayOcclusionCache implements OcclusionCache {
+
+ private final int reachX2;
+ private final byte[] cache;
+ private int positionKey;
+ private int entry;
+ private int offset;
+
+ public ArrayOcclusionCache(int reach) {
+ this.reachX2 = reach * 2;
+ this.cache = new byte[(reachX2 * reachX2 * reachX2) / 4];
+ }
+
+ @Override
+ public void resetCache() {
+ Arrays.fill(cache, (byte) 0);
+ }
+
+ @Override
+ public void setVisible(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ cache[entry] |= 1 << offset;
+ }
+
+ @Override
+ public void setHidden(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ cache[entry] |= 1 << offset + 1;
+ }
+
+ @Override
+ public int getState(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ return cache[entry] >> offset & 3;
+ }
+
+ @Override
+ public void setLastVisible() {
+ cache[entry] |= 1 << offset;
+ }
+
+ @Override
+ public void setLastHidden() {
+ cache[entry] |= 1 << offset + 1;
+ }
+
+}
diff --git a/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java b/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a2e5620fb2b1a71fbca2068fc049bfa89a47737
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java
@@ -0,0 +1,17 @@
+package com.logisticscraft.occlusionculling.cache;
+
+public interface OcclusionCache {
+
+ void resetCache();
+
+ void setVisible(int x, int y, int z);
+
+ void setHidden(int x, int y, int z);
+
+ int getState(int x, int y, int z);
+
+ void setLastHidden();
+
+ void setLastVisible();
+
+}
diff --git a/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java b/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb28265631b079eb5da8ae3a7ecca6e343f8c0b6
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java
@@ -0,0 +1,25 @@
+package com.logisticscraft.occlusionculling.util;
+
+/**
+ * Contains MathHelper methods
+ */
+public final class MathUtilities {
+
+ private MathUtilities() {
+ }
+
+ public static int floor(double d) {
+ int i = (int) d;
+ return d < (double) i ? i - 1 : i;
+ }
+
+ public static int fastFloor(double d) {
+ return (int) (d + 1024.0) - 1024;
+ }
+
+ public static int ceil(double d) {
+ int i = (int) d;
+ return d > (double) i ? i + 1 : i;
+ }
+
+}
diff --git a/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java b/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e3cb9e11f65af0627164c8dbd6aad3e5690d36c
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java
@@ -0,0 +1,87 @@
+package com.logisticscraft.occlusionculling.util;
+
+public class Vec3d {
+
+ public double x;
+ public double y;
+ public double z;
+
+ public Vec3d(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public double getZ() {
+ return z;
+ }
+
+ public void set(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public void setAdd(Vec3d vec, double x, double y, double z) {
+ this.x = vec.x + x;
+ this.y = vec.y + y;
+ this.z = vec.z + z;
+ }
+
+ public Vec3d div(Vec3d rayDir) {
+ this.x /= rayDir.x;
+ this.z /= rayDir.z;
+ this.y /= rayDir.y;
+ return this;
+ }
+
+ public Vec3d normalize() {
+ double mag = Math.sqrt(x*x+y*y+z*z);
+ this.x /= mag;
+ this.y /= mag;
+ this.z /= mag;
+ return this;
+ }
+
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Vec3d)) {
+ return false;
+ }
+ Vec3d vec3d = (Vec3d) other;
+ if (Double.compare(vec3d.x, x) != 0) {
+ return false;
+ }
+ if (Double.compare(vec3d.y, y) != 0) {
+ return false;
+ }
+ return Double.compare(vec3d.z, z) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ long l = Double.doubleToLongBits(x);
+ int i = (int) (l ^ l >>> 32);
+ l = Double.doubleToLongBits(y);
+ i = 31 * i + (int) (l ^ l >>> 32);
+ l = Double.doubleToLongBits(z);
+ i = 31 * i + (int) (l ^ l >>> 32);
+ return i;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + x + ", " + y + ", " + z + ")";
+ }
+
+}
diff --git a/src/main/java/dev/tr7zw/entityculling/CullTask.java b/src/main/java/dev/tr7zw/entityculling/CullTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..57e36d4a2c770a3d2ae72a78e69802dd119e6999
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/CullTask.java
@@ -0,0 +1,152 @@
+package dev.tr7zw.entityculling;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import ca.spottedleaf.moonrise.common.util.TickThread;
+import com.logisticscraft.occlusionculling.OcclusionCullingInstance;
+import com.logisticscraft.occlusionculling.util.Vec3d;
+
+import dev.tr7zw.entityculling.versionless.access.Cullable;
+import me.earthme.luminol.config.modules.experiment.RayTrackingEntityTrackerConfig;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.decoration.ArmorStand;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+
+public class CullTask implements Runnable {
+
+ private volatile boolean requestCull = false;
+ private volatile boolean scheduleNext = true;
+ private volatile boolean inited = false;
+
+ private final OcclusionCullingInstance culling;
+ private final Player checkTarget;
+
+ private final int hitboxLimit;
+
+ public long lastCheckedTime = 0;
+
+ // reused preallocated vars
+ private final Vec3d lastPos = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMin = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMax = new Vec3d(0, 0, 0);
+
+ private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> {
+ final TickThread worker = new TickThread("EntityCulling") {
+ @Override
+ public void run() {
+ task.run();
+ }
+ };
+
+ worker.setDaemon(true);
+
+ return worker;
+ });
+
+ private final Executor worker;
+
+ public CullTask(
+ OcclusionCullingInstance culling,
+ Player checkTarget,
+ int hitboxLimit,
+ long checkIntervalMs
+ ) {
+ this.culling = culling;
+ this.checkTarget = checkTarget;
+ this.hitboxLimit = hitboxLimit;
+ this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker);
+ }
+
+ public void requestCullSignal() {
+ this.requestCull = true;
+ }
+
+ public void signalStop() {
+ this.scheduleNext = false;
+ }
+
+ public void setup() {
+ if (!this.inited)
+ this.inited = true;
+ else
+ return;
+ this.worker.execute(this);
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (this.checkTarget.tickCount > 10) {
+ // getEyePosition can use a fixed delta as its debug only anyway
+ Vec3 cameraMC = this.checkTarget.getEyePosition(0);
+ if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) {
+ long start = System.currentTimeMillis();
+
+ requestCull = false;
+
+ lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z);
+ culling.resetCache();
+
+ cullEntities(cameraMC, lastPos);
+
+ lastCheckedTime = (System.currentTimeMillis() - start);
+ }
+ }
+ }finally {
+ if (this.scheduleNext) {
+ this.worker.execute(this);
+ }
+ }
+ }
+
+ private void cullEntities(Vec3 cameraMC, Vec3d camera) {
+ for (Entity entity : this.checkTarget.level().getEntities().getAll()) {
+ if (!(entity instanceof Cullable cullable)) {
+ continue; // Not sure how this could happen outside from mixin screwing up the inject into
+ // Entity
+ }
+
+ if (entity.getType().skipRaytracningCheck) {
+ continue;
+ }
+
+ if (!cullable.isForcedVisible()) {
+ if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) {
+ cullable.setCulled(false);
+ continue;
+ }
+
+ if (!entity.position().closerThan(cameraMC, me.earthme.luminol.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance)) {
+ cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just
+ // render it
+ continue;
+ }
+
+ AABB boundingBox = entity.getBoundingBox();
+ if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit
+ || boundingBox.getZsize() > hitboxLimit) {
+ cullable.setCulled(false); // To big to bother to cull
+ continue;
+ }
+
+ aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ);
+ aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ);
+
+ boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera);
+
+ cullable.setCulled(!visible);
+ }
+ }
+ }
+
+ private boolean isSkippableArmorstand(Entity entity) {
+ if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands)
+ return false;
+ return entity instanceof ArmorStand && entity.isInvisible();
+ }
+}
diff --git a/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java b/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..aadf7cdc4a28ecf92853e147fa115d43c89f6fe8
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java
@@ -0,0 +1,43 @@
+package dev.tr7zw.entityculling;
+
+import com.logisticscraft.occlusionculling.DataProvider;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.status.ChunkStatus;
+
+public class DefaultChunkDataProvider implements DataProvider {
+ private final Level level;
+
+ public DefaultChunkDataProvider(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public boolean prepareChunk(int chunkX, int chunkZ) {
+ return this.level.getChunkIfLoaded(chunkX, chunkZ) != null;
+ }
+
+ @Override
+ public boolean isOpaqueFullCube(int x, int y, int z) {
+ BlockPos pos = new BlockPos(x, y, z);
+
+ final ChunkAccess access = this.level.getChunkIfLoaded(pos);
+ if (access == null) {
+ return false;
+ }
+
+ if (this.level.isOutsideBuildHeight(pos)) {
+ return Blocks.VOID_AIR.defaultBlockState().isSolidRender();
+ } else {
+ return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截()
+ }
+ }
+
+ @Override
+ public void cleanup() {
+ DataProvider.super.cleanup();
+ }
+
+}
diff --git a/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java b/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java
new file mode 100644
index 0000000000000000000000000000000000000000..948e8e934793532704161e0a129ebf86355ba5a8
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java
@@ -0,0 +1,17 @@
+package dev.tr7zw.entityculling.versionless.access;
+
+public interface Cullable {
+
+ public void setTimeout();
+
+ public boolean isForcedVisible();
+
+ public void setCulled(boolean value);
+
+ public boolean isCulled();
+
+ public void setOutOfCamera(boolean value);
+
+ public boolean isOutOfCamera();
+
+}
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/RayTrackingEntityTrackerConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/RayTrackingEntityTrackerConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e3e6a500c9eb26a06f5441f9e542dc9b1ad0cf4
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/RayTrackingEntityTrackerConfig.java
@@ -0,0 +1,28 @@
+package me.earthme.luminol.config.modules.experiment;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class RayTrackingEntityTrackerConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+ @ConfigInfo(baseName = "skip_marker_armor_stands")
+ public static boolean skipMarkerArmorStands = true;
+ @ConfigInfo(baseName = "check_interval_ms")
+ public static int checkIntervalMs = 10;
+ @ConfigInfo(baseName = "tracing_distance")
+ public static int tracingDistance = 48;
+ @ConfigInfo(baseName = "hitbox_limit")
+ public static int hitboxLimit = 50;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.EXPERIMENT;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "ray_tracking_entity_tracker";
+ }
+}

View File

@@ -0,0 +1,60 @@
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java
@@ -1,0 +_,57 @@
+package com.logisticscraft.occlusionculling.cache;
+
+import java.util.Arrays;
+
+public class ArrayOcclusionCache implements OcclusionCache {
+
+ private final int reachX2;
+ private final byte[] cache;
+ private int positionKey;
+ private int entry;
+ private int offset;
+
+ public ArrayOcclusionCache(int reach) {
+ this.reachX2 = reach * 2;
+ this.cache = new byte[(reachX2 * reachX2 * reachX2) / 4];
+ }
+
+ @Override
+ public void resetCache() {
+ Arrays.fill(cache, (byte) 0);
+ }
+
+ @Override
+ public void setVisible(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ cache[entry] |= 1 << offset;
+ }
+
+ @Override
+ public void setHidden(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ cache[entry] |= 1 << offset + 1;
+ }
+
+ @Override
+ public int getState(int x, int y, int z) {
+ positionKey = x + y * reachX2 + z * reachX2 * reachX2;
+ entry = positionKey / 4;
+ offset = (positionKey % 4) * 2;
+ return cache[entry] >> offset & 3;
+ }
+
+ @Override
+ public void setLastVisible() {
+ cache[entry] |= 1 << offset;
+ }
+
+ @Override
+ public void setLastHidden() {
+ cache[entry] |= 1 << offset + 1;
+ }
+
+}

View File

@@ -0,0 +1,20 @@
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java
@@ -1,0 +_,17 @@
+package com.logisticscraft.occlusionculling.cache;
+
+public interface OcclusionCache {
+
+ void resetCache();
+
+ void setVisible(int x, int y, int z);
+
+ void setHidden(int x, int y, int z);
+
+ int getState(int x, int y, int z);
+
+ void setLastHidden();
+
+ void setLastVisible();
+
+}

View File

@@ -0,0 +1,28 @@
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java
@@ -1,0 +_,25 @@
+package com.logisticscraft.occlusionculling.util;
+
+/**
+ * Contains MathHelper methods
+ */
+public final class MathUtilities {
+
+ private MathUtilities() {
+ }
+
+ public static int floor(double d) {
+ int i = (int) d;
+ return d < (double) i ? i - 1 : i;
+ }
+
+ public static int fastFloor(double d) {
+ return (int) (d + 1024.0) - 1024;
+ }
+
+ public static int ceil(double d) {
+ int i = (int) d;
+ return d > (double) i ? i + 1 : i;
+ }
+
+}

View File

@@ -0,0 +1,90 @@
--- /dev/null
+++ b/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java
@@ -1,0 +_,87 @@
+package com.logisticscraft.occlusionculling.util;
+
+public class Vec3d {
+
+ public double x;
+ public double y;
+ public double z;
+
+ public Vec3d(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public double getZ() {
+ return z;
+ }
+
+ public void set(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public void setAdd(Vec3d vec, double x, double y, double z) {
+ this.x = vec.x + x;
+ this.y = vec.y + y;
+ this.z = vec.z + z;
+ }
+
+ public Vec3d div(Vec3d rayDir) {
+ this.x /= rayDir.x;
+ this.z /= rayDir.z;
+ this.y /= rayDir.y;
+ return this;
+ }
+
+ public Vec3d normalize() {
+ double mag = Math.sqrt(x*x+y*y+z*z);
+ this.x /= mag;
+ this.y /= mag;
+ this.z /= mag;
+ return this;
+ }
+
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Vec3d)) {
+ return false;
+ }
+ Vec3d vec3d = (Vec3d) other;
+ if (Double.compare(vec3d.x, x) != 0) {
+ return false;
+ }
+ if (Double.compare(vec3d.y, y) != 0) {
+ return false;
+ }
+ return Double.compare(vec3d.z, z) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ long l = Double.doubleToLongBits(x);
+ int i = (int) (l ^ l >>> 32);
+ l = Double.doubleToLongBits(y);
+ i = 31 * i + (int) (l ^ l >>> 32);
+ l = Double.doubleToLongBits(z);
+ i = 31 * i + (int) (l ^ l >>> 32);
+ return i;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + x + ", " + y + ", " + z + ")";
+ }
+
+}

View File

@@ -1,15 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 11:07:09 +0800
Subject: [PATCH] Kaiiju Entity tick and removal limiter
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
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityLimits.java
@@ -0,0 +1,141 @@
@@ -1,0 +_,141 @@
+package dev.kaiijumc.kaiiju;
+
+import java.io.File;
@@ -151,122 +142,3 @@ index 0000000000000000000000000000000000000000..40e80fc685a42bbaeea3e6e647541211
+ }
+ }
+}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityThrottler.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityThrottler.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb690efacf083e4ff3e321578b12c534e6a40196
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityThrottler.java
@@ -0,0 +1,84 @@
+package dev.kaiijumc.kaiiju;
+
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import net.minecraft.world.entity.Entity;
+import io.papermc.paper.threadedregions.RegionizedWorldData;
+
+public class KaiijuEntityThrottler {
+ private static class TickInfo {
+ int currentTick;
+ int continueFrom;
+ int toTick;
+ int toRemove;
+ }
+
+ public static class EntityThrottlerReturn {
+ public boolean skip;
+ public boolean remove;
+ }
+
+ private final Object2ObjectOpenHashMap<KaiijuEntityLimits.EntityLimit, TickInfo> entityLimitTickInfoMap = new Object2ObjectOpenHashMap<>();
+
+ public void tickLimiterStart() {
+ for (TickInfo tickInfo : entityLimitTickInfoMap.values()) {
+ tickInfo.currentTick = 0;
+ }
+ }
+
+ public EntityThrottlerReturn tickLimiterShouldSkip(Entity entity) {
+ EntityThrottlerReturn retVal = new EntityThrottlerReturn();
+ if (entity.isRemoved()) return retVal;
+ KaiijuEntityLimits.EntityLimit entityLimit = KaiijuEntityLimits.getEntityLimit(entity);
+
+ if (entityLimit != null) {
+ TickInfo tickInfo = entityLimitTickInfoMap.computeIfAbsent(entityLimit, el -> {
+ TickInfo newTickInfo = new TickInfo();
+ newTickInfo.toTick = entityLimit.limit();
+ return newTickInfo;
+ });
+
+ tickInfo.currentTick++;
+ if (tickInfo.currentTick <= tickInfo.toRemove && entityLimit.removal() > 0) {
+ retVal.skip = false;
+ retVal.remove = true;
+ return retVal;
+ }
+
+ if (tickInfo.currentTick < tickInfo.continueFrom) {
+ retVal.skip = true;
+ return retVal;
+ }
+ if (tickInfo.currentTick - tickInfo.continueFrom < tickInfo.toTick) {
+ retVal.skip = false;
+ return retVal;
+ }
+ retVal.skip = true;
+ return retVal;
+ } else {
+ retVal.skip = false;
+ return retVal;
+ }
+ }
+
+ public void tickLimiterFinish(RegionizedWorldData regionizedWorldData) {
+ for (var entry : entityLimitTickInfoMap.entrySet()) {
+ KaiijuEntityLimits.EntityLimit entityLimit = entry.getKey();
+ TickInfo tickInfo = entry.getValue();
+
+ int additionals = 0;
+ int nextContinueFrom = tickInfo.continueFrom + tickInfo.toTick;
+ if (nextContinueFrom >= tickInfo.currentTick) {
+ additionals = entityLimit.limit() - (tickInfo.currentTick - tickInfo.continueFrom);
+ nextContinueFrom = 0;
+ }
+ tickInfo.continueFrom = nextContinueFrom;
+ tickInfo.toTick = entityLimit.limit() + additionals;
+
+ if (tickInfo.toRemove == 0 && tickInfo.currentTick > entityLimit.removal()) {
+ tickInfo.toRemove = tickInfo.currentTick - entityLimit.removal();
+ } else if (tickInfo.toRemove != 0) {
+ tickInfo.toRemove = 0;
+ }
+ }
+ }
+}
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
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/KaiijuEntityLimiterConfig.java
@@ -0,0 +1,23 @@
+package me.earthme.luminol.config.modules.misc;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import dev.kaiijumc.kaiiju.KaiijuEntityLimits;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class KaiijuEntityLimiterConfig implements IConfigModule {
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "kaiiju_entity_limiter";
+ }
+
+ @Override
+ public void onLoaded(CommentedFileConfig configInstance) {
+ KaiijuEntityLimits.init();
+ }
+}

View File

@@ -0,0 +1,87 @@
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuEntityThrottler.java
@@ -1,0 +_,84 @@
+package dev.kaiijumc.kaiiju;
+
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import net.minecraft.world.entity.Entity;
+import io.papermc.paper.threadedregions.RegionizedWorldData;
+
+public class KaiijuEntityThrottler {
+ private static class TickInfo {
+ int currentTick;
+ int continueFrom;
+ int toTick;
+ int toRemove;
+ }
+
+ public static class EntityThrottlerReturn {
+ public boolean skip;
+ public boolean remove;
+ }
+
+ private final Object2ObjectOpenHashMap<KaiijuEntityLimits.EntityLimit, TickInfo> entityLimitTickInfoMap = new Object2ObjectOpenHashMap<>();
+
+ public void tickLimiterStart() {
+ for (TickInfo tickInfo : entityLimitTickInfoMap.values()) {
+ tickInfo.currentTick = 0;
+ }
+ }
+
+ public EntityThrottlerReturn tickLimiterShouldSkip(Entity entity) {
+ EntityThrottlerReturn retVal = new EntityThrottlerReturn();
+ if (entity.isRemoved()) return retVal;
+ KaiijuEntityLimits.EntityLimit entityLimit = KaiijuEntityLimits.getEntityLimit(entity);
+
+ if (entityLimit != null) {
+ TickInfo tickInfo = entityLimitTickInfoMap.computeIfAbsent(entityLimit, el -> {
+ TickInfo newTickInfo = new TickInfo();
+ newTickInfo.toTick = entityLimit.limit();
+ return newTickInfo;
+ });
+
+ tickInfo.currentTick++;
+ if (tickInfo.currentTick <= tickInfo.toRemove && entityLimit.removal() > 0) {
+ retVal.skip = false;
+ retVal.remove = true;
+ return retVal;
+ }
+
+ if (tickInfo.currentTick < tickInfo.continueFrom) {
+ retVal.skip = true;
+ return retVal;
+ }
+ if (tickInfo.currentTick - tickInfo.continueFrom < tickInfo.toTick) {
+ retVal.skip = false;
+ return retVal;
+ }
+ retVal.skip = true;
+ return retVal;
+ } else {
+ retVal.skip = false;
+ return retVal;
+ }
+ }
+
+ public void tickLimiterFinish(RegionizedWorldData regionizedWorldData) {
+ for (var entry : entityLimitTickInfoMap.entrySet()) {
+ KaiijuEntityLimits.EntityLimit entityLimit = entry.getKey();
+ TickInfo tickInfo = entry.getValue();
+
+ int additionals = 0;
+ int nextContinueFrom = tickInfo.continueFrom + tickInfo.toTick;
+ if (nextContinueFrom >= tickInfo.currentTick) {
+ additionals = entityLimit.limit() - (tickInfo.currentTick - tickInfo.continueFrom);
+ nextContinueFrom = 0;
+ }
+ tickInfo.continueFrom = nextContinueFrom;
+ tickInfo.toTick = entityLimit.limit() + additionals;
+
+ if (tickInfo.toRemove == 0 && tickInfo.currentTick > entityLimit.removal()) {
+ tickInfo.toRemove = tickInfo.currentTick - entityLimit.removal();
+ } else if (tickInfo.toRemove != 0) {
+ tickInfo.toRemove = 0;
+ }
+ }
+ }
+}

View File

@@ -0,0 +1,155 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/CullTask.java
@@ -1,0 +_,152 @@
+package dev.tr7zw.entityculling;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import ca.spottedleaf.moonrise.common.util.TickThread;
+import com.logisticscraft.occlusionculling.OcclusionCullingInstance;
+import com.logisticscraft.occlusionculling.util.Vec3d;
+
+import dev.tr7zw.entityculling.versionless.access.Cullable;
+import me.earthme.luminol.config.modules.experiment.RayTrackingEntityTrackerConfig;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.decoration.ArmorStand;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+
+public class CullTask implements Runnable {
+
+ private volatile boolean requestCull = false;
+ private volatile boolean scheduleNext = true;
+ private volatile boolean inited = false;
+
+ private final OcclusionCullingInstance culling;
+ private final Player checkTarget;
+
+ private final int hitboxLimit;
+
+ public long lastCheckedTime = 0;
+
+ // reused preallocated vars
+ private final Vec3d lastPos = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMin = new Vec3d(0, 0, 0);
+ private final Vec3d aabbMax = new Vec3d(0, 0, 0);
+
+ private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> {
+ final TickThread worker = new TickThread("EntityCulling") {
+ @Override
+ public void run() {
+ task.run();
+ }
+ };
+
+ worker.setDaemon(true);
+
+ return worker;
+ });
+
+ private final Executor worker;
+
+ public CullTask(
+ OcclusionCullingInstance culling,
+ Player checkTarget,
+ int hitboxLimit,
+ long checkIntervalMs
+ ) {
+ this.culling = culling;
+ this.checkTarget = checkTarget;
+ this.hitboxLimit = hitboxLimit;
+ this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker);
+ }
+
+ public void requestCullSignal() {
+ this.requestCull = true;
+ }
+
+ public void signalStop() {
+ this.scheduleNext = false;
+ }
+
+ public void setup() {
+ if (!this.inited)
+ this.inited = true;
+ else
+ return;
+ this.worker.execute(this);
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (this.checkTarget.tickCount > 10) {
+ // getEyePosition can use a fixed delta as its debug only anyway
+ Vec3 cameraMC = this.checkTarget.getEyePosition(0);
+ if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) {
+ long start = System.currentTimeMillis();
+
+ requestCull = false;
+
+ lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z);
+ culling.resetCache();
+
+ cullEntities(cameraMC, lastPos);
+
+ lastCheckedTime = (System.currentTimeMillis() - start);
+ }
+ }
+ }finally {
+ if (this.scheduleNext) {
+ this.worker.execute(this);
+ }
+ }
+ }
+
+ private void cullEntities(Vec3 cameraMC, Vec3d camera) {
+ for (Entity entity : this.checkTarget.level().getEntities().getAll()) {
+ if (!(entity instanceof Cullable cullable)) {
+ continue; // Not sure how this could happen outside from mixin screwing up the inject into
+ // Entity
+ }
+
+ if (entity.getType().skipRaytracningCheck) {
+ continue;
+ }
+
+ if (!cullable.isForcedVisible()) {
+ if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) {
+ cullable.setCulled(false);
+ continue;
+ }
+
+ if (!entity.position().closerThan(cameraMC, me.earthme.luminol.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance)) {
+ cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just
+ // render it
+ continue;
+ }
+
+ AABB boundingBox = entity.getBoundingBox();
+ if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit
+ || boundingBox.getZsize() > hitboxLimit) {
+ cullable.setCulled(false); // To big to bother to cull
+ continue;
+ }
+
+ aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ);
+ aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ);
+
+ boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera);
+
+ cullable.setCulled(!visible);
+ }
+ }
+ }
+
+ private boolean isSkippableArmorstand(Entity entity) {
+ if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands)
+ return false;
+ return entity instanceof ArmorStand && entity.isInvisible();
+ }
+}

View File

@@ -0,0 +1,46 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java
@@ -1,0 +_,43 @@
+package dev.tr7zw.entityculling;
+
+import com.logisticscraft.occlusionculling.DataProvider;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.chunk.ChunkAccess;
+import net.minecraft.world.level.chunk.status.ChunkStatus;
+
+public class DefaultChunkDataProvider implements DataProvider {
+ private final Level level;
+
+ public DefaultChunkDataProvider(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public boolean prepareChunk(int chunkX, int chunkZ) {
+ return this.level.getChunkIfLoaded(chunkX, chunkZ) != null;
+ }
+
+ @Override
+ public boolean isOpaqueFullCube(int x, int y, int z) {
+ BlockPos pos = new BlockPos(x, y, z);
+
+ final ChunkAccess access = this.level.getChunkIfLoaded(pos);
+ if (access == null) {
+ return false;
+ }
+
+ if (this.level.isOutsideBuildHeight(pos)) {
+ return Blocks.VOID_AIR.defaultBlockState().isSolidRender();
+ } else {
+ return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截()
+ }
+ }
+
+ @Override
+ public void cleanup() {
+ DataProvider.super.cleanup();
+ }
+
+}

View File

@@ -0,0 +1,20 @@
--- /dev/null
+++ b/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java
@@ -1,0 +_,17 @@
+package dev.tr7zw.entityculling.versionless.access;
+
+public interface Cullable {
+
+ public void setTimeout();
+
+ public boolean isForcedVisible();
+
+ public void setCulled(boolean value);
+
+ public boolean isCulled();
+
+ public void setOutOfCamera(boolean value);
+
+ public boolean isOutOfCamera();
+
+}

View File

@@ -1,15 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 15:26:09 +0800
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 @@
@@ -1,0 +_,133 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import com.google.common.reflect.TypeToken;
@@ -143,107 +134,3 @@ index 0000000000000000000000000000000000000000..2b830cb288ceba390ed39cd33fc1ee85
+ }
+ }
+}
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c01e5b5de685eca7edbe8a87732efd45d4dd2557
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java
@@ -0,0 +1,44 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import io.sentry.Sentry;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class SentryManager {
+
+ private static final Logger logger = LogManager.getLogger(SentryManager.class);
+
+ private SentryManager() {
+
+ }
+
+ private static boolean initialized = false;
+
+ public static synchronized void init(Level logLevel) {
+ if (initialized) {
+ return;
+ }
+ if (logLevel == null) {
+ logger.error("Invalid log level, defaulting to WARN.");
+ logLevel = Level.WARN;
+ }
+ try {
+ initialized = true;
+
+ Sentry.init(options -> {
+ options.setDsn(me.earthme.luminol.config.modules.misc.SentryConfig.sentryDsn);
+ options.setMaxBreadcrumbs(100);
+ });
+
+ PufferfishSentryAppender appender = new PufferfishSentryAppender(logLevel);
+ appender.start();
+ ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).addAppender(appender);
+ logger.info("Sentry logging started!");
+ } catch (Exception e) {
+ logger.warn("Failed to initialize sentry!", e);
+ initialized = false;
+ }
+ }
+
+}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..55d6bb635b182d15471bfcd481a2b7c6ce26c00b
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java
@@ -0,0 +1,47 @@
+package me.earthme.luminol.config.modules.misc;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import org.apache.logging.log4j.Level;
+
+public class SentryConfig implements IConfigModule {
+
+ @ConfigInfo(baseName = "dsn", comments =
+ " Sentry DSN for improved error logging, leave blank to disable,\n" +
+ " Obtain from https://sentry.io/")
+ public static String sentryDsn = "";
+
+ @ConfigInfo(baseName = "log_level", comments = " Logs with a level higher than or equal to this level will be recorded.")
+ public static String logLevel = "WARN";
+
+ @ConfigInfo(baseName = "only_log_thrown", comments = " Only log with a Throwable will be recorded after enabling this.")
+ public static boolean onlyLogThrown = true;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "sentry";
+ }
+
+ @Override
+ public void onLoaded(CommentedFileConfig configInstance) {
+ String sentryEnvironment = System.getenv("SENTRY_DSN");
+
+ sentryDsn = sentryEnvironment != null && !sentryEnvironment.isBlank()
+ ? sentryEnvironment
+ : configInstance.getOrElse("sentry.dsn", sentryDsn);
+
+ logLevel = configInstance.getOrElse("sentry.log-level", logLevel);
+ onlyLogThrown = configInstance.getOrElse("sentry.only-log-thrown", onlyLogThrown);
+
+ if (sentryDsn != null && !sentryDsn.isBlank()) {
+ gg.pufferfish.pufferfish.sentry.SentryManager.init(Level.getLevel(logLevel));
+ }
+ }
+}
\ No newline at end of file

View File

@@ -0,0 +1,47 @@
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java
@@ -1,0 +_,44 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import io.sentry.Sentry;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class SentryManager {
+
+ private static final Logger logger = LogManager.getLogger(SentryManager.class);
+
+ private SentryManager() {
+
+ }
+
+ private static boolean initialized = false;
+
+ public static synchronized void init(Level logLevel) {
+ if (initialized) {
+ return;
+ }
+ if (logLevel == null) {
+ logger.error("Invalid log level, defaulting to WARN.");
+ logLevel = Level.WARN;
+ }
+ try {
+ initialized = true;
+
+ Sentry.init(options -> {
+ options.setDsn(me.earthme.luminol.config.modules.misc.SentryConfig.sentryDsn);
+ options.setMaxBreadcrumbs(100);
+ });
+
+ PufferfishSentryAppender appender = new PufferfishSentryAppender(logLevel);
+ appender.start();
+ ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).addAppender(appender);
+ logger.info("Sentry logging started!");
+ } catch (Exception e) {
+ logger.warn("Failed to initialize sentry!", e);
+ initialized = false;
+ }
+ }
+
+}

View File

@@ -0,0 +1,30 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/RegionStatsImpl.java
@@ -1,0 +_,27 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.RegionStats;
+
+public class RegionStatsImpl implements RegionStats {
+ private final TickRegions.RegionStats internal;
+
+ public RegionStatsImpl(TickRegions.RegionStats internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public int getEntityCount() {
+ return this.internal.getEntityCount();
+ }
+
+ @Override
+ public int getPlayerCount() {
+ return this.internal.getPlayerCount();
+ }
+
+ @Override
+ public int getChunkCount() {
+ return this.internal.getChunkCount();
+ }
+}

View File

@@ -0,0 +1,50 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionImpl.java
@@ -1,0 +_,47 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.ThreadedRegionizer;
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.ThreadedRegion;
+import me.earthme.luminol.api.TickRegionData;
+import net.minecraft.world.level.ChunkPos;
+import org.bukkit.Location;
+import org.bukkit.World;
+
+import javax.annotation.Nullable;
+
+public class ThreadedRegionImpl implements ThreadedRegion {
+ private final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> internal;
+
+ public ThreadedRegionImpl(ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> internal) {
+ this.internal = internal;
+ }
+
+ @Nullable
+ @Override
+ public Location getCenterChunkPos() {
+ final ChunkPos centerChunkPos = this.internal.getCenterChunk();
+
+ if (centerChunkPos == null) {
+ return null;
+ }
+
+ return new Location(this.internal.regioniser.world.getWorld(), centerChunkPos.getMiddleBlockX(), 0, centerChunkPos.getMiddleBlockZ());
+ }
+
+ @Override
+ public double getDeadSectionPercent() {
+ return this.internal.getDeadSectionPercent();
+ }
+
+ @Override
+ public TickRegionData getTickRegionData() {
+ return new TickRegionDataImpl(this.internal.getData());
+ }
+
+ @Nullable
+ @Override
+ public World getWorld() {
+ return this.internal.regioniser.world.getWorld();
+ }
+}

View File

@@ -0,0 +1,56 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/ThreadedRegionizerImpl.java
@@ -1,0 +_,53 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.ThreadedRegion;
+import me.earthme.luminol.api.ThreadedRegionizer;
+import net.minecraft.server.level.ServerLevel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ThreadedRegionizerImpl implements ThreadedRegionizer {
+ private final ServerLevel internal;
+
+ public ThreadedRegionizerImpl(ServerLevel internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public Collection<ThreadedRegion> getAllRegions() {
+ final List<ThreadedRegion> ret = new ArrayList<>();
+
+ this.internal.regioniser.computeForAllRegions(region -> {
+ final ThreadedRegion wrapped = new ThreadedRegionImpl(region);
+
+ ret.add(wrapped);
+ });
+
+ return ret;
+ }
+
+ @Override
+ public ThreadedRegion getAtSynchronized(int chunkX, int chunkZ) {
+ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> got = this.internal.regioniser.getRegionAtSynchronised(chunkX, chunkZ);
+
+ if (got == null) {
+ return null;
+ }
+
+ return new ThreadedRegionImpl(got);
+ }
+
+ @Override
+ public ThreadedRegion getAtUnSynchronized(int chunkX, int chunkZ) {
+ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> got = this.internal.regioniser.getRegionAtUnsynchronised(chunkX, chunkZ);
+
+ if (got == null) {
+ return null;
+ }
+
+ return new ThreadedRegionImpl(got);
+ }
+}

View File

@@ -0,0 +1,33 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/api/impl/TickRegionDataImpl.java
@@ -1,0 +_,30 @@
+package me.earthme.luminol.api.impl;
+
+import io.papermc.paper.threadedregions.TickRegions;
+import me.earthme.luminol.api.RegionStats;
+import me.earthme.luminol.api.TickRegionData;
+import org.bukkit.World;
+
+public class TickRegionDataImpl implements TickRegionData {
+ private final TickRegions.TickRegionData internal;
+
+ public TickRegionDataImpl(TickRegions.TickRegionData internal) {
+ this.internal = internal;
+ }
+
+ @Override
+ public World getWorld() {
+ return this.internal.world.getWorld();
+ }
+
+ @Override
+ public long getCurrentTickCount() {
+ return this.internal.getCurrentTick();
+ }
+
+ @Override
+ public RegionStats getRegionStats() {
+ return new RegionStatsImpl(this.internal.getRegionStats());
+ }
+
+}

View File

@@ -0,0 +1,73 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
@@ -1,0 +_,70 @@
+package me.earthme.luminol.commands;
+
+import me.earthme.luminol.config.LuminolConfig;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.TextColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LuminolConfigCommand extends Command {
+ public LuminolConfigCommand(){
+ super("luminolconfig");
+ this.setPermission("luminol.commands.luminolconfig");
+ this.setDescription("Manage config file");
+ this.setUsage("/luminolconfig");
+ }
+
+ @Override
+ public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) throws IllegalArgumentException {
+ final List<String> result = new ArrayList<>();
+
+ if (args.length == 1){
+ result.add("reload");
+ }
+
+ return result;
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
+ if (!this.testPermission(sender)){
+ sender.sendMessage(Component
+ .text("No permission to execute this command!")
+ .color(TextColor.color(255,0,0))
+ );
+ }
+
+ if (args.length < 1){
+ sender.sendMessage(
+ Component
+ .text("Wrong use!\n")
+ .color(TextColor.color(255,0,0))
+ );
+ return true;
+ }
+
+ switch (args[0]){
+ case "reload" -> {
+ LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ Component
+ .text("Reloaded config file!")
+ .color(TextColor.color(0,255,0))
+ ));
+ }
+
+ default -> sender.sendMessage(
+ Component
+ .text("Unknown action!\n")
+ .color(TextColor.color(255,0,0))
+ );
+ }
+
+ return true;
+ }
+}

View File

@@ -0,0 +1,50 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/commands/MembarCommand.java
@@ -1,0 +_,47 @@
+package me.earthme.luminol.commands;
+
+import me.earthme.luminol.config.modules.misc.MembarConfig;
+import me.earthme.luminol.functions.GlobalServerMemoryBar;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.TextColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class MembarCommand extends Command {
+ public MembarCommand(@NotNull String name) {
+ super(name);
+ this.setPermission("luminol.commands.membar");
+ this.setDescription("Show the memory usage through a bossbar");
+ this.setUsage("/membar");
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
+ if (!testPermission(sender)){
+ return true;
+ }
+
+ if (!MembarConfig.memoryBarEnabled){
+ sender.sendMessage(Component.text("Membar was already disabled!").color(TextColor.color(255,0,0)));
+ return true;
+ }
+
+ if (!(sender instanceof Player player)){
+ sender.sendMessage(Component.text("Only player can use this command!").color(TextColor.color(255,0,0)));
+ return true;
+ }
+
+ if (GlobalServerMemoryBar.isPlayerVisible(player)) {
+ player.sendMessage(Component.text("Disabled mem bar").color(TextColor.color(0,255,0)));
+ GlobalServerMemoryBar.setVisibilityForPlayer(player,false);
+ return true;
+ }
+
+ player.sendMessage(Component.text("Enabled mem bar").color(TextColor.color(0,255,0)));
+ GlobalServerMemoryBar.setVisibilityForPlayer(player,true);
+
+ return true;
+ }
+}

View File

@@ -0,0 +1,50 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/commands/RegionBarCommand.java
@@ -1,0 +_,47 @@
+package me.earthme.luminol.commands;
+
+import me.earthme.luminol.config.modules.misc.RegionBarConfig;
+import me.earthme.luminol.functions.GlobalServerRegionBar;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.TextColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class RegionBarCommand extends Command {
+ public RegionBarCommand(@NotNull String name) {
+ super(name);
+ this.setPermission("luminol.commands.regionbar");
+ this.setDescription("Show info about your current region through a bossbar");
+ this.setUsage("/regionbar");
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
+ if (!testPermission(sender)) {
+ return true;
+ }
+
+ if (!RegionBarConfig.regionbarEnabled) {
+ sender.sendMessage(Component.text("Regionbar was already disabled!").color(TextColor.color(255, 0, 0)));
+ return true;
+ }
+
+ if (!(sender instanceof Player player)) {
+ sender.sendMessage(Component.text("Only player can use this command!").color(TextColor.color(255, 0, 0)));
+ return true;
+ }
+
+ if (GlobalServerRegionBar.isPlayerVisible(player)) {
+ player.sendMessage(Component.text("Disabled region bar").color(TextColor.color(0, 255, 0)));
+ GlobalServerRegionBar.setVisibilityForPlayer(player, false);
+ return true;
+ }
+
+ player.sendMessage(Component.text("Enabled region bar").color(TextColor.color(0, 255, 0)));
+ GlobalServerRegionBar.setVisibilityForPlayer(player, true);
+
+ return true;
+ }
+}

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