Start hard-fork from Luminol
This commit is contained in:
@@ -1,72 +1,152 @@
|
||||
--- a/luminol-server/build.gradle.kts
|
||||
+++ b/luminol-server/build.gradle.kts
|
||||
@@ -50,7 +_,23 @@
|
||||
--- a/folia-server/build.gradle.kts
|
||||
+++ b/folia-server/build.gradle.kts
|
||||
@@ -7,15 +_,16 @@
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
idea
|
||||
- id("io.papermc.paperweight.core")
|
||||
+ id("moe.luminolmc.hyacinthusweight.core") // TODO Later - rebrand
|
||||
id("io.papermc.fill.gradle") version "1.0.12"
|
||||
}
|
||||
|
||||
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||
+val bacteriawaMavenPublicUrl = "https://repo.bacteriawa.com/repository/maven-public/"
|
||||
|
||||
dependencies {
|
||||
mache("io.papermc:mache:26.2+build.1")
|
||||
- paperclip("io.papermc:paperclip:3.0.4")
|
||||
+ hyacinthusclip("moe.luminolmc:hyacinthusclip:${providers.gradleProperty("clipVersion").get()}") // TODO Later - rebrand
|
||||
}
|
||||
|
||||
paperweight {
|
||||
@@ -23,7 +_,8 @@
|
||||
filterPatches = false
|
||||
gitFilePatches = false
|
||||
|
||||
- val fork = forks.register("folia") {
|
||||
+ val folia = forks.register("folia") {
|
||||
+ rootDirectory = upstreamsDirectory().map { it.dir("folia") }
|
||||
upstream.patchDir("paperServer") {
|
||||
upstreamPath = "paper-server"
|
||||
excludes = setOf("src/minecraft", "patches", "build.gradle.kts")
|
||||
@@ -32,7 +_,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
- activeFork = luminol
|
||||
- activeFork = fork
|
||||
+ val lophine = forks.register("lophine") {
|
||||
+ forks = luminol
|
||||
+ forks = folia
|
||||
+ upstream.patchRepo("paperServer") {
|
||||
+ upstreamRepo = luminol.patchedRepo("paperServer")
|
||||
+ upstreamRepo = folia.patchedRepo("paperServer")
|
||||
+ patchesDir = rootDirectory.dir("lophine-server/paper-patches")
|
||||
+ outputDir = rootDirectory.dir("paper-server")
|
||||
+ }
|
||||
+
|
||||
+ upstream.patchDir("luminolServer") {
|
||||
+ upstreamPath = "luminol-server"
|
||||
+ upstream.patchDir("foliaServer") {
|
||||
+ upstreamPath = "folia-server"
|
||||
+ excludes = setOf("src/minecraft", "paper-patches", "minecraft-patches", "build.gradle.kts", "build.gradle.kts.patch")
|
||||
+ patchesDir = rootDirectory.dir("lophine-server/luminol-patches")
|
||||
+ outputDir = rootDirectory.dir("luminol-server")
|
||||
+ patchesDir = rootDirectory.dir("lophine-server/folia-patches")
|
||||
+ outputDir = rootDirectory.dir("folia-server")
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ activeFork = lophine
|
||||
|
||||
|
||||
updatingMinecraft {
|
||||
@@ -44,6 +_,7 @@
|
||||
libraryRepositories.addAll(
|
||||
"https://repo.maven.apache.org/maven2/",
|
||||
paperMavenPublicUrl,
|
||||
+ bacteriawaMavenPublicUrl
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,12 +_,16 @@
|
||||
@@ -103,10 +_,14 @@
|
||||
main {
|
||||
java { srcDir("../paper-server/src/main/java"); srcDir("../paper-server/src/generated/java") }
|
||||
resources { srcDir("../paper-server/src/main/resources") }
|
||||
java { srcDir("../folia-server/src/main/java") }
|
||||
resources { srcDir("../folia-server/src/main/resources") }
|
||||
+ java { srcDir("../luminol-server/src/main/java") }
|
||||
+ resources { srcDir("../luminol-server/src/main/resources") }
|
||||
+ java { srcDir("../folia-server/src/main/java") }
|
||||
+ resources { srcDir("../folia-server/src/main/resources") }
|
||||
}
|
||||
test {
|
||||
java { srcDir("../paper-server/src/test/java") }
|
||||
resources { srcDir("../paper-server/src/test/resources") }
|
||||
java { srcDir("../folia-server/src/test/java") }
|
||||
resources { srcDir("../folia-server/src/test/resources") }
|
||||
+ java { srcDir("../luminol-server/src/main/java") }
|
||||
+ resources { srcDir("../luminol-server/src/main/resources") }
|
||||
+ java { srcDir("../folia-server/src/test/java") }
|
||||
+ resources { srcDir("../folia-server/src/test/resources") }
|
||||
}
|
||||
}
|
||||
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
||||
@@ -158,7 +_,7 @@
|
||||
@@ -134,7 +_,21 @@
|
||||
}
|
||||
|
||||
dependencies {
|
||||
- implementation(project(":luminol-api"))
|
||||
+ implementation(project(":lophine-api"))
|
||||
// Luminol start - Dependenices insert
|
||||
implementation("net.objecthunter:exp4j:0.4.8")
|
||||
implementation("com.electronwill.night-config:toml:3.9.0") // Night config
|
||||
@@ -234,14 +_,14 @@
|
||||
- implementation(project(":folia-api"))
|
||||
+ implementation(project(":lophine-api")) // Lophine - api update
|
||||
+ // Lophine start - Dependenices insert
|
||||
+ implementation("net.objecthunter:exp4j:0.4.8")
|
||||
+ implementation("com.electronwill.night-config:toml:3.9.0") // Night config
|
||||
+ implementation("com.github.luben:zstd-jni:1.5.4-1")
|
||||
+ implementation("net.openhft:zero-allocation-hashing:0.16")
|
||||
+ implementation("io.github.classgraph:classgraph:4.8.158")
|
||||
+ implementation("net.openhft:affinity:3.23.3")
|
||||
+ // Leaves start - leaves plugin
|
||||
+ implementation("org.spongepowered:configurate-gson:4.2.0-SNAPSHOT") {
|
||||
+ exclude(group = "com.google.code.gson", module = "gson")
|
||||
+ exclude(group = "com.google.guava", module = "guava")
|
||||
+ }
|
||||
+ // Leaves end - leaves plugin
|
||||
+ // Lophine end
|
||||
implementation("ca.spottedleaf:leafpile:1.0.0")
|
||||
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
|
||||
@@ -189,21 +_,22 @@
|
||||
val git = Git(rootProject.layout.projectDirectory.path)
|
||||
val mcVersion = rootProject.providers.gradleProperty("mcVersion").get()
|
||||
val build = System.getenv("BUILD_NUMBER") ?: null
|
||||
- val buildTime = providers.environmentVariable("BUILD_STARTED_AT").map(Instant::parse).orElse(Instant.EPOCH).get()
|
||||
+ 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",
|
||||
- "Implementation-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Implementation-Title" to "Lophine", // Luminol - Rebrand
|
||||
- "Implementation-Title" to "Folia",
|
||||
+ "Implementation-Title" to "Lophine", // Lophine - Rebrand
|
||||
"Implementation-Version" to implementationVersion,
|
||||
"Implementation-Vendor" to date,
|
||||
- "Specification-Title" to "Luminol", // Luminol - Rebrand
|
||||
+ "Specification-Title" to "Lophine", // Luminol - Rebrand
|
||||
- "Specification-Title" to "Folia",
|
||||
+ "Specification-Title" to "Lophine", // Lophine - Rebrand
|
||||
"Specification-Version" to project.version,
|
||||
"Specification-Vendor" to "LuminoLMC", // Luminol - Rebrand
|
||||
- "Brand-Id" to "luminolmc:luminol", // Luminol - Rebrand
|
||||
- "Brand-Name" to "Luminol", // Luminol - Rebrand
|
||||
+ "Brand-Id" to "luminolmc:lophine", // Luminol - Rebrand
|
||||
+ "Brand-Name" to "Lophine", // Luminol - Rebrand
|
||||
- "Specification-Vendor" to "Paper Team",
|
||||
- "Brand-Id" to "papermc:folia",
|
||||
- "Brand-Name" to "Folia",
|
||||
+ // TODO Later - rebrand org name
|
||||
+ "Specification-Vendor" to "LuminoLMC", // Lophine - Rebrand
|
||||
+ "Brand-Id" to "luminolmc:lophine", // Lophine - Rebrand
|
||||
+ "Brand-Name" to "Lophine", // Lophine - Rebrand
|
||||
"Build-Number" to (build ?: ""),
|
||||
"Build-Time" to buildTime.toString(),
|
||||
"Git-Branch" to gitBranch,
|
||||
@@ -214,6 +_,20 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+// Pufferfish Start
|
||||
+tasks.withType<JavaCompile> {
|
||||
+ val compilerArgs = options.compilerArgs
|
||||
+ compilerArgs.add("--add-modules=jdk.incubator.vector")
|
||||
+}
|
||||
+// Pufferfish End
|
||||
+// Lophine start - Hide unnecessary warnings
|
||||
+tasks.withType<JavaCompile> {
|
||||
+ val compilerArgs = options.compilerArgs
|
||||
+ compilerArgs.add("-Xlint:-module")
|
||||
+ compilerArgs.add("-Xlint:-removal")
|
||||
+ compilerArgs.add("-Xlint:-dep-ann")
|
||||
+}
|
||||
+// Lophine end
|
||||
|
||||
// Compile tests with -parameters for better junit parameterized test names
|
||||
tasks.compileTestJava {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 8 Jun 2025 00:58:13 +0800
|
||||
Subject: [PATCH] Rebrand to Lophine
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index 3b700b214ac6818cd75c34b207aa1436f52231e7..315c137cb9dbac51a8ac0d63f0ae0127e57c6c9f 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -25,6 +25,7 @@ public class ConfigManager {
|
||||
|
||||
public static void initConfigs() {
|
||||
registerConfig("luminol", builder.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
+ registerConfig("lophine", builder.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
|
||||
preLoad();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
|
||||
index e4022494b050b68d54bac3cde87bdfc9e908859c..a4188ef831825764c0756b826651e2e7a9f99c5b 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java
|
||||
@@ -8,7 +8,7 @@ import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
@ConfigClassInfo(category = EnumConfigCategory.MISC, name = "server_mod_name")
|
||||
public class ServerModNameConfig implements IConfigModule {
|
||||
@ConfigInfo(name = "name", comments = "Decides the server mod name shown in your F3 debug screen.")
|
||||
- public static String serverModName = "Luminol";
|
||||
+ public static String serverModName = "Lophine";
|
||||
|
||||
@ConfigInfo(name = "vanilla_spoof", comments = "Ignore any plugin's modification and server mod name set in this config block, only force sending brand name of vanilla")
|
||||
public static boolean fakeVanilla = false;
|
||||
@@ -1,141 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 16 Mar 2026 15:51:40 +0800
|
||||
Subject: [PATCH] Diff in auto-update patch
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
index ce01352b637547c1cf8308d56d4b3f9c48fcca70..9b5623ce1de3d68c949c3c00b966cedab3a4c986 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/AutoUpdateConfig.java
|
||||
@@ -16,13 +16,13 @@ import java.util.Set;
|
||||
category = EnumConfigCategory.MISC,
|
||||
name = "auto_update",
|
||||
comments = """
|
||||
- Checks GitHub Releases for newer Luminol jars on a schedule.
|
||||
- Downloads are staged under auto_update/luminol and written to auto_update/core.path,
|
||||
+ Checks GitHub Releases for newer version's jars on a schedule.
|
||||
+ Downloads are staged under auto_update/lophine and written to auto_update/core.path,
|
||||
which Hyacinthusclip can consume on the next restart.
|
||||
- If target_jar_path is set, Luminol will also try to replace that launcher jar directly."""
|
||||
+ If target_jar_path is set, server will also try to replace that launcher jar directly."""
|
||||
)
|
||||
public class AutoUpdateConfig implements IConfigModule {
|
||||
- @ConfigInfo(name = "enabled", comments = "Whether Luminol should check for updates automatically.")
|
||||
+ @ConfigInfo(name = "enabled", comments = "Whether the server should check for updates automatically.")
|
||||
public static boolean enabled = false;
|
||||
|
||||
@ConfigInfo(name = "check_times", comments = "List of daily check times in HH:mm, based on the server's local time zone.")
|
||||
@@ -33,7 +33,7 @@ public class AutoUpdateConfig implements IConfigModule {
|
||||
|
||||
@ConfigInfo(name = "target_jar_path", comments = """
|
||||
Optional launcher jar path to replace after a successful download.
|
||||
- Leave this blank to keep the downloaded jar staged in auto_update/luminol
|
||||
+ Leave this blank to keep the downloaded jar staged in auto_update/lophine
|
||||
and let Hyacinthusclip switch to it through auto_update/core.path on restart.""")
|
||||
public static String targetJarPath = "";
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
index 94a25cd681c9352d6931edafd9ec67fd7ba8a777..d0d0cf5e5ff8d4b8efa4d9778c27267b41cf8cf8 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/AutoUpdateHelper.java
|
||||
@@ -35,10 +35,10 @@ public final class AutoUpdateHelper {
|
||||
private final Logger LOGGER = LogUtils.getClassLogger();
|
||||
private final Gson GSON = new Gson();
|
||||
|
||||
- private final String GITHUB_API_BASE = "https://api.github.com/repos/LuminolMC/Luminol";
|
||||
+ private final String GITHUB_API_BASE = "https://api.github.com/repos/lophineMC/lophine";
|
||||
private final Path AUTO_UPDATE_DIR = Path.of("auto_update");
|
||||
private final Path CORE_PATH_FILE = AUTO_UPDATE_DIR.resolve("core.path");
|
||||
- private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("luminol");
|
||||
+ private final Path LUMINOL_UPDATE_DIR = AUTO_UPDATE_DIR.resolve("lophine");
|
||||
private final Path LATEST_PATH_FILE = LUMINOL_UPDATE_DIR.resolve("latest.path");
|
||||
private final long DAILY_TASK_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
@@ -51,13 +51,13 @@ public final class AutoUpdateHelper {
|
||||
ensureWorkingDirectories();
|
||||
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor(task -> {
|
||||
- final Thread thread = new Thread(task, "Luminol Auto Update Scheduler");
|
||||
+ final Thread thread = new Thread(task, "Lophine Auto Update Scheduler");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
|
||||
if (AutoUpdateConfig.checkTimes.isEmpty()) {
|
||||
- LOGGER.warn("Luminol auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
+ LOGGER.warn("Lophine auto-update is enabled, but misc.auto_update.check_times is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,14 +95,14 @@ public final class AutoUpdateHelper {
|
||||
|
||||
private void checkForUpdatesSafely() {
|
||||
if (!UPDATE_RUNNING.compareAndSet(false, true)) {
|
||||
- LOGGER.info("A Luminol auto-update check is already running, skipping this schedule.");
|
||||
+ LOGGER.info("A Lophine auto-update check is already running, skipping this schedule.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
checkForUpdates();
|
||||
} catch (Exception e) {
|
||||
- LOGGER.warn("Luminol auto-update failed.", e);
|
||||
+ LOGGER.warn("Lophine auto-update failed.", e);
|
||||
} finally {
|
||||
UPDATE_RUNNING.set(false);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final ReleaseAssetInfo latestRelease = getLatestCompatibleRelease(mcVersion, gitBranch);
|
||||
if (latestRelease == null) {
|
||||
- LOGGER.warn("No compatible Luminol release was found for Minecraft {}{}.",
|
||||
+ LOGGER.warn("No compatible Lophine release was found for Minecraft {}{}.",
|
||||
mcVersion,
|
||||
gitBranch == null ? "" : " on branch " + gitBranch
|
||||
);
|
||||
@@ -132,7 +132,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
final UpdateStatus updateStatus = compareReleaseWithCurrentBuild(latestRelease.releaseCommitHash(), currentGitHash);
|
||||
if (updateStatus == UpdateStatus.UP_TO_DATE) {
|
||||
- LOGGER.info("You are already running the latest compatible Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("You are already running the latest compatible Lophine release: {}", latestRelease.tagName());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public final class AutoUpdateHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
- LOGGER.info("Found a newer Luminol release: {}", latestRelease.tagName());
|
||||
+ LOGGER.info("Found a newer Lophine release: {}", latestRelease.tagName());
|
||||
|
||||
final Path stagedJar = downloadAndStageRelease(latestRelease);
|
||||
final Path finalJarPath = tryApplyTargetJar(stagedJar);
|
||||
@@ -163,7 +163,7 @@ public final class AutoUpdateHelper {
|
||||
|
||||
if (finalJarPath.equals(stagedJar)) {
|
||||
LOGGER.info(
|
||||
- "Downloaded the latest Luminol jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
+ "Downloaded the latest Lophine jar to {} and refreshed auto_update/core.path for Hyacinthusclip. Please restart your server.",
|
||||
finalJarPath.toAbsolutePath()
|
||||
);
|
||||
} else {
|
||||
@@ -179,7 +179,7 @@ public final class AutoUpdateHelper {
|
||||
try {
|
||||
Files.createDirectories(LUMINOL_UPDATE_DIR);
|
||||
} catch (IOException e) {
|
||||
- throw new RuntimeException("Failed to create Luminol auto update directory", e);
|
||||
+ throw new RuntimeException("Failed to create Lophine auto update directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ public final class AutoUpdateHelper {
|
||||
private @NotNull HttpURLConnection openConnection(String url) throws IOException, URISyntaxException {
|
||||
final HttpURLConnection connection = (HttpURLConnection) new URI(url).toURL().openConnection();
|
||||
connection.setRequestProperty("Accept", "application/vnd.github+json");
|
||||
- connection.setRequestProperty("User-Agent", "Luminol Auto Update");
|
||||
+ connection.setRequestProperty("User-Agent", "Lophine Auto Update");
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(10000);
|
||||
return connection;
|
||||
@@ -1,190 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 13 Aug 2025 22:23:46 +0800
|
||||
Subject: [PATCH] Leaves: Item overstack util
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
index a5df7e40369cf2c309f4d37fede6615f34a467e2..84d0e1a7cd687ac4ed9f1bf824ca28940c2fab1e 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java
|
||||
@@ -17,10 +17,98 @@
|
||||
|
||||
package org.leavesmc.leaves.util;
|
||||
|
||||
+import fun.bm.lophine.config.modules.function.ContainerExpansionConfig;
|
||||
+import net.minecraft.core.component.DataComponents;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.world.entity.item.ItemEntity;
|
||||
+import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.item.component.CustomData;
|
||||
+import net.minecraft.world.item.component.ItemContainerContents;
|
||||
+import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+import java.util.List;
|
||||
+import java.util.Objects;
|
||||
+import java.util.Optional;
|
||||
|
||||
// Only used part of the original code was copied
|
||||
public class ItemOverstackUtils {
|
||||
+
|
||||
+ private static final List<ItemUtil> overstackUtils = List.of(
|
||||
+ new ShulkerBox()
|
||||
+ );
|
||||
+
|
||||
+ public static int getItemStackMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxServerStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static int getNetworkMaxCount(ItemStack stack) {
|
||||
+ int size;
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && (size = util.getMaxClientStackCount(stack)) != -1) {
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+ return stack.getMaxStackSize();
|
||||
+ }
|
||||
+
|
||||
+ public static boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled() && util.tryStackItems(self, other)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static boolean hasOverstackingItem() {
|
||||
+ for (ItemUtil util : overstackUtils) {
|
||||
+ if (util.isEnabled()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static int getItemStackMaxCountReal(ItemStack stack) {
|
||||
+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag();
|
||||
+ return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize());
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ int modifiedMaxStackSize = getNetworkMaxCount(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.putInt("Leaves.RealStackSize", realMaxStackSize);
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) {
|
||||
+ int realMaxStackSize = getItemStackMaxCountReal(itemStack);
|
||||
+ if (itemStack.getMaxStackSize() != realMaxStackSize) {
|
||||
+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize);
|
||||
+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
+ nbt.remove("Leaves.RealStackSize");
|
||||
+ if (nbt.isEmpty()) {
|
||||
+ itemStack.remove(DataComponents.CUSTOM_DATA);
|
||||
+ } else {
|
||||
+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt));
|
||||
+ }
|
||||
+ }
|
||||
+ return itemStack;
|
||||
+ }
|
||||
+
|
||||
public static float getItemStackSignalStrength(int maxStackSize, ItemStack itemStack) {
|
||||
float result = (float) itemStack.getCount() / Math.min(maxStackSize, itemStack.getMaxStackSize());
|
||||
/*if (LeavesConfig.modify.oldMC.allowGrindstoneOverstacking && CurseEnchantedBook.isCursedEnchantedBook(itemStack)) { // Luminol
|
||||
@@ -28,4 +116,80 @@ public class ItemOverstackUtils {
|
||||
}*/ // Luminol
|
||||
return Math.clamp(result, 0f, 1f);
|
||||
}
|
||||
+
|
||||
+ public static boolean isStackable(ItemStack itemStack) {
|
||||
+ return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged());
|
||||
+ }
|
||||
+
|
||||
+ private interface ItemUtil {
|
||||
+ boolean isEnabled();
|
||||
+
|
||||
+ boolean tryStackItems(ItemEntity self, ItemEntity other);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ int getMaxServerStackCount(ItemStack stack);
|
||||
+
|
||||
+ // number -> modified count, -1 -> I don't care
|
||||
+ default int getMaxClientStackCount(ItemStack stack) {
|
||||
+ return getMaxServerStackCount(stack);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static class ShulkerBox implements ItemUtil {
|
||||
+ public static boolean shulkerBoxCheck(@NotNull ItemStack stack1, @NotNull ItemStack stack2) {
|
||||
+ if (ContainerExpansionConfig.nbtShulkerStackable) {
|
||||
+ return Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
+ }
|
||||
+ return shulkerBoxNoItem(stack1) && shulkerBoxNoItem(stack2) && Objects.equals(stack1.getComponents(), stack2.getComponents());
|
||||
+ }
|
||||
+
|
||||
+ public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) {
|
||||
+ // Leaves - Paper 26.1: ItemContainerContents#stream() removed, use nonEmptyItemCopyStream()
|
||||
+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).nonEmptyItemCopyStream().findAny().isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isEnabled() {
|
||||
+ return ContainerExpansionConfig.shulkerCount > 1;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean tryStackItems(ItemEntity self, ItemEntity other) {
|
||||
+ ItemStack selfStack = self.getItem();
|
||||
+ if (!(selfStack.getItem() instanceof BlockItem blockItem) || !(blockItem.getBlock() instanceof ShulkerBoxBlock)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ ItemStack otherStack = other.getItem();
|
||||
+ if (selfStack.getItem() == otherStack.getItem()
|
||||
+ && shulkerBoxCheck(selfStack, otherStack)
|
||||
+ && selfStack.getCount() != ContainerExpansionConfig.shulkerCount) {
|
||||
+ int amount = Math.min(otherStack.getCount(), ContainerExpansionConfig.shulkerCount - selfStack.getCount());
|
||||
+
|
||||
+ selfStack.grow(amount);
|
||||
+ self.setItem(selfStack);
|
||||
+
|
||||
+ self.pickupDelay = Math.max(other.pickupDelay, self.pickupDelay);
|
||||
+ self.age = Math.min(other.getAge(), self.age);
|
||||
+
|
||||
+ otherStack.shrink(amount);
|
||||
+ if (otherStack.isEmpty()) {
|
||||
+ other.discard();
|
||||
+ } else {
|
||||
+ other.setItem(otherStack);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxServerStackCount(ItemStack stack) {
|
||||
+ if (stack.getItem() instanceof BlockItem bi &&
|
||||
+ bi.getBlock() instanceof ShulkerBoxBlock && (ContainerExpansionConfig.nbtShulkerStackable || shulkerBoxNoItem(stack))) {
|
||||
+ return ContainerExpansionConfig.shulkerCount;
|
||||
+ }
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 18 Feb 2026 00:15:08 +0800
|
||||
Subject: [PATCH] Leaves: Fakeplayer
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
index a4c188f71564fc77a9fa22b4cae032e1919d06f2..019266803f1452cb1e76350da8edae10a77020ac 100644
|
||||
--- a/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/utils/FoliaServerWaypointManager.java
|
||||
@@ -54,6 +54,12 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Leaves start - fakeplayer
|
||||
+ if (waypoint instanceof org.leavesmc.leaves.bot.ServerBot bot && !bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.ENABLE_LOCATOR_BAR)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
+
|
||||
this.waypoints.add(waypoint);
|
||||
|
||||
for (ServerPlayer toCreateFor : this.trackingPlayers) {
|
||||
@@ -110,6 +116,11 @@ public class FoliaServerWaypointManager extends ServerWaypointManager {
|
||||
this.trackingPlayers.add(player);
|
||||
|
||||
scheduleIfOffTarget(player, () -> {
|
||||
+ // Leaves start - fakeplayer
|
||||
+ if (player instanceof org.leavesmc.leaves.bot.ServerBot) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Leaves end - fakeplayer
|
||||
for (WaypointTransmitter transmitter : this.waypoints) {
|
||||
this.createConnection(player, transmitter);
|
||||
}
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 063cc27df9c8f3ad5c8db5cedcaa3d2bccf6dc24..5ad6aab5e72e27bb402494873770ab5822601939 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -11,14 +11,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
private final Set<String> availableFeatures = new HashSet<>();
|
||||
|
||||
private ServerFeatureManager() {
|
||||
- if (false) { // Luminol not provide this
|
||||
- availableFeatures.addAll(Set.of(
|
||||
- FAKEPLAYER,
|
||||
- PHOTOGRAPHER,
|
||||
- BYTEBUF,
|
||||
- UPDATE_SUPPRESSION_EVENT
|
||||
- ));
|
||||
- }
|
||||
+ availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 17 May 2026 05:33:21 +0800
|
||||
Subject: [PATCH] Leaves: Replay Mod API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 5ad6aab5e72e27bb402494873770ab5822601939..0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -12,6 +12,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
|
||||
private ServerFeatureManager() {
|
||||
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
+ availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Wed, 3 Jun 2026 13:49:39 +0800
|
||||
Subject: [PATCH] Update suppression event
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
index 0ac9edfa36833a7ebe0353c4aff40955ab3ddf8c..c3db6c5281728fa1a2b4d84f9ebff9fcfd696698 100644
|
||||
--- a/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
+++ b/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java
|
||||
@@ -13,6 +13,7 @@ public class ServerFeatureManager implements FeatureManager {
|
||||
private ServerFeatureManager() {
|
||||
availableFeatures.add(FAKEPLAYER); // Lophine - fakeplayer support
|
||||
availableFeatures.add(PHOTOGRAPHER); // Lophine - Replay Mod API support
|
||||
+ availableFeatures.add(UPDATE_SUPPRESSION_EVENT); // Lophine - update suppression event support
|
||||
if (Boolean.getBoolean("leavesclip.enable.mixin") || Boolean.getBoolean("hyacinthusclip.enable.mixin")) {
|
||||
availableFeatures.add(MIXIN);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Sun, 22 Mar 2026 01:39:17 +0800
|
||||
Subject: [PATCH] Carpet features
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
index 315c137cb9dbac51a8ac0d63f0ae0127e57c6c9f..2a2d6aff636ad960638b357d224a631c89d23d33 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
|
||||
@@ -26,6 +26,15 @@ public class ConfigManager {
|
||||
public static void initConfigs() {
|
||||
registerConfig("luminol", builder.of("luminol", "me.earthme.luminol.config.modules"));
|
||||
registerConfig("lophine", builder.of("lophine", "fun.bm.lophine.config.modules")); // add lophine global config
|
||||
+ // Lophine start - add carpet config
|
||||
+ registerConfig("lophine_carpet", builder.of(
|
||||
+ new java.io.File("lophine_config"),
|
||||
+ "lophine_carpet",
|
||||
+ "lophine_carpet_config.toml",
|
||||
+ "lophinecarpetconfig",
|
||||
+ "fun.bm.lophine.carpet.config.modules"
|
||||
+ ));
|
||||
+ // Lophine end - add carpet config
|
||||
preLoad();
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 5 Jun 2026 16:10:25 +0800
|
||||
Subject: [PATCH] Carpet Features Compatible
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
index f079a1cd99d648dc7ca97fb65406b7a42ad5a74e..30f78cbae7aea3e9fcee6d97f229ddf8e8344299 100644
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
+++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandConfig.java
|
||||
@@ -23,9 +23,4 @@ public class CommandConfig implements IConfigModule {
|
||||
""")
|
||||
@HotReloadUnsupported
|
||||
public static boolean waypointsAndWaypointCommand = false;
|
||||
- @ConfigInfo(name = "enable_tick_command", comments = """
|
||||
- Only freeze/unfreeze/step/query command is allowed if you enabled it.
|
||||
- WARN: This should disabled in production environment!
|
||||
- """)
|
||||
- public static boolean tick = false;
|
||||
}
|
||||
diff --git a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java b/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
|
||||
deleted file mode 100644
|
||||
index f791feed92abd750ac10775c05150f122ecbe886..0000000000000000000000000000000000000000
|
||||
--- a/src/main/java/me/earthme/luminol/config/modules/optimizations/OptimizedDragonRespawnConfig.java
|
||||
+++ /dev/null
|
||||
@@ -1,12 +0,0 @@
|
||||
-package me.earthme.luminol.config.modules.optimizations;
|
||||
-
|
||||
-import me.earthme.luminol.config.IConfigModule;
|
||||
-import me.earthme.luminol.config.flags.ConfigClassInfo;
|
||||
-import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
-import me.earthme.luminol.enums.EnumConfigCategory;
|
||||
-
|
||||
-@ConfigClassInfo(category = EnumConfigCategory.OPTIMIZATIONS, name = "end_dragon")
|
||||
-public class OptimizedDragonRespawnConfig implements IConfigModule {
|
||||
- @ConfigInfo(name = "optimized_dragon_respawn")
|
||||
- public static boolean optimizedRespawn = false;
|
||||
-}
|
||||
@@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 14 Jun 2026 18:10:20 +0800
|
||||
Subject: [PATCH] Luminol Config System
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
|
||||
index a4d608d64b7d3477c9144d93547fd3b4f39a1b02..2a75f8fbd2e5f41ca138740319d34683915e3b5b 100644
|
||||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -107,6 +107,7 @@ public class Main {
|
||||
JvmProfiler.INSTANCE.start(Environment.SERVER);
|
||||
}
|
||||
|
||||
+ me.earthme.luminol.config.ConfigManager.initConfigs(); // Luminol - Luminol config
|
||||
io.papermc.paper.plugin.PluginInitializerManager.load(options); // Paper
|
||||
Bootstrap.bootStrap();
|
||||
Bootstrap.validate();
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 6f13870a1b463049dd37cf1c65d0bdecfc35b5c4..a49c46eb7df50fc3c5587a2c3668ab6edc887107 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1169,6 +1169,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
ca.spottedleaf.moonrise.common.util.MoonriseCommon.haltExecutors();
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
+ // Luminol start - Config Systems
|
||||
+ me.earthme.luminol.config.ConfigManager.saveConfigs(false);
|
||||
+ // Luminol end
|
||||
// Paper start - Improved watchdog support - move final shutdown items here
|
||||
Util.shutdownExecutors();
|
||||
this.onServerExit();
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index cd5551c0221ad2a7b5c7d452d8d91ffc9711c3ee..1ad4704523a3d90414ac514488207b1b5def9afd 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -238,6 +238,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
+ me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // 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()) {
|
||||
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 17:56:30 +0800
|
||||
Subject: [PATCH] Correct player respawn place
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index fbe0ef19bfabfc42d9e0e08e17b08159321b3804..44b3dfbf529630d8cca9a4270ae2a7c94c5a077c 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -511,8 +511,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
double amountX = selectMaxX - selectMinX;
|
||||
double amountZ = selectMaxZ - selectMinZ;
|
||||
|
||||
- int selectX = amountX < 1.0 ? Mth.floor(worldBorder.getCenterX()) : (int)Mth.floor((amountX + 1.0) * random.nextDouble() + selectMinX);
|
||||
- int selectZ = amountZ < 1.0 ? Mth.floor(worldBorder.getCenterZ()) : (int)Mth.floor((amountZ + 1.0) * random.nextDouble() + selectMinZ);
|
||||
+ // Luminol start - Correct player respawn place
|
||||
+ int selectX = amountX < 0.0 ? Mth.floor(worldBorder.getCenterX()) : (int)Mth.floor(amountX * random.nextDouble() + selectMinX);
|
||||
+ int selectZ = amountZ < 0.0 ? Mth.floor(worldBorder.getCenterZ()) : (int)Mth.floor(amountZ * random.nextDouble() + selectMinZ);
|
||||
+ // Luminol end - Correct player respawn place
|
||||
|
||||
return new BlockPos(selectX, 0, selectZ);
|
||||
}
|
||||
@@ -523,10 +525,20 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
|
||||
private static BlockPos findSpawnAround(ServerLevel world, BlockPos selected) {
|
||||
+ // Luminol start - Correct player respawn place
|
||||
+ BlockPos inChunk = PlayerSpawnFinder.getLevelRespawnPos(world, selected.getX(), selected.getZ());
|
||||
+ if (inChunk != null) {
|
||||
+ AABB checkVolume = PlayerSpawnFinder.PLAYER_DIMENSIONS.makeBoundingBox((double)inChunk.getX() + 0.5, (double)inChunk.getY(), (double)inChunk.getZ() + 0.5);
|
||||
+
|
||||
+ if (world.noCollision(null, checkVolume, true)) {
|
||||
+ return inChunk;
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end - Correct player respawn place
|
||||
// try hard to find, so that we don't attempt another chunk load
|
||||
for (int dz = -SPAWN_RADIUS_SELECTION_SEARCH; dz <= SPAWN_RADIUS_SELECTION_SEARCH; ++dz) {
|
||||
for (int dx = -SPAWN_RADIUS_SELECTION_SEARCH; dx <= SPAWN_RADIUS_SELECTION_SEARCH; ++dx) {
|
||||
- BlockPos inChunk = PlayerSpawnFinder.getLevelRespawnPos(world, selected.getX() + dx, selected.getZ() + dz);
|
||||
+ inChunk = PlayerSpawnFinder.getLevelRespawnPos(world, selected.getX() + dx, selected.getZ() + dz); // Luminol - Correct player respawn place
|
||||
if (inChunk == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -2018,7 +2030,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
|
||||
if (newLevel.dimension() == lastDimension) {
|
||||
- this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit
|
||||
+ this.connection.internalTeleport(PositionMoveRotation.of(transition), transition.relatives()); // CraftBukkit // Luminol - Correct player respawn place
|
||||
this.connection.resetPosition();
|
||||
transition.postTeleportTransition().onTransition(this);
|
||||
return this;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:01:59 +0800
|
||||
Subject: [PATCH] Correct volatile reference get in RegionizedTaskQueue
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
|
||||
index d1a045d47dcd12f246d95ecdfc202da357897cbf..b264dbd13a392cde3f24ff75c0034985fda68ccc 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
|
||||
@@ -533,7 +533,7 @@ public final class RegionizedTaskQueue {
|
||||
}
|
||||
|
||||
private ReferenceCountData getReferenceCounterVolatile() {
|
||||
- return (ReferenceCountData)REFERENCE_COUNTER_HANDLE.get(this);
|
||||
+ return (ReferenceCountData)REFERENCE_COUNTER_HANDLE.getVolatile(this); // Luminol - Correct volatile reference get in RegionizedTaskQueue
|
||||
}
|
||||
|
||||
private ReferenceCountData compareAndExchangeReferenceCounter(final ReferenceCountData expect, final ReferenceCountData update) {
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Tue, 30 Jun 2026 22:34:00 +0800
|
||||
Subject: [PATCH] Correct thread unsafe random sources
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
|
||||
index 01b3cda3da79abd30860eb33491ac00f9e958767..dd35e72757b1be1a73e67b272c138bb4e3b6336a 100644
|
||||
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
|
||||
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
|
||||
@@ -30,7 +30,7 @@ public class WanderingTraderSpawner implements CustomSpawner {
|
||||
private static final int SPAWN_CHANCE_INCREASE = 25;
|
||||
private static final int SPAWN_ONE_IN_X_CHANCE = 10;
|
||||
private static final int NUMBER_OF_SPAWN_ATTEMPTS = 10;
|
||||
- private final RandomSource random = RandomSource.create();
|
||||
+ private final RandomSource random = io.papermc.paper.threadedregions.util.ThreadLocalRandomSource.INSTANCE; // Luminol - Correct thread unsafe random sources
|
||||
private final SavedDataStorage savedDataStorage;
|
||||
// Folia - moved to global data
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java b/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java
|
||||
index 22b9f70f76ff8f592359e958fa439e9806a29fcc..818598ed4e498bf3f177faac03336097b41915ee 100644
|
||||
--- a/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java
|
||||
@@ -28,7 +28,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable
|
||||
public float rot;
|
||||
public float oRot;
|
||||
public float tRot;
|
||||
- private static final RandomSource RANDOM = RandomSource.create();
|
||||
+ private static final RandomSource RANDOM = io.papermc.paper.threadedregions.util.ThreadLocalRandomSource.INSTANCE; // Luminol - Correct thread unsafe random sources
|
||||
private @Nullable Component name;
|
||||
|
||||
public EnchantingTableBlockEntity(final BlockPos worldPosition, final BlockState blockState) {
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 2 Jul 2026 22:31:15 +0800
|
||||
Subject: [PATCH] Correct portal logic of some projectile entities
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/ShulkerBullet.java b/net/minecraft/world/entity/projectile/ShulkerBullet.java
|
||||
index d5506bfc84912ec50cd5391225b9b5291435d3aa..6339a770526324bdc1bcc0c0e3bacc0a10f359ab 100644
|
||||
--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java
|
||||
+++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java
|
||||
@@ -229,7 +229,7 @@ public class ShulkerBullet extends Projectile {
|
||||
this.setPos(this.position().add(movement));
|
||||
this.applyEffectsFromBlocks();
|
||||
if (this.portalProcess != null && this.portalProcess.isInsidePortalThisTick()) {
|
||||
- this.handlePortal();
|
||||
+ if (this.handlePortal()) return; // Luminol - Correct portal logic of some projectile entities (Should not be ticking anymore after portal logics)
|
||||
}
|
||||
|
||||
if (hitResult != null && this.isAlive() && hitResult.getType() != HitResult.Type.MISS) {
|
||||
diff --git a/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java b/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java
|
||||
index 88c2f0f927bd8376522eb9aed184abd6f09230f6..d66a4826400eca835645e1115c4fefc61715f336 100644
|
||||
--- a/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java
|
||||
+++ b/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java
|
||||
@@ -276,7 +276,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
.clipIncludingBorder(
|
||||
new ClipContext(originalPosition, originalPosition.add(movement), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)
|
||||
);
|
||||
- this.stepMoveAndHit(blockHitResult);
|
||||
+ if (this.stepMoveAndHit(blockHitResult)) return; // Luminol - Correct portal logic of some projectile entities (Should not be ticking anymore after portal logics)
|
||||
} else {
|
||||
this.setPos(originalPosition.add(movement));
|
||||
this.applyEffectsFromBlocks();
|
||||
@@ -299,7 +299,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
return 0.99F;
|
||||
}
|
||||
|
||||
- private void stepMoveAndHit(final BlockHitResult blockHitResult) {
|
||||
+ private boolean stepMoveAndHit(final BlockHitResult blockHitResult) { // Luminol - Correct portal logic of some projectile entities
|
||||
while (this.isAlive()) {
|
||||
Vec3 initialPosition = this.position();
|
||||
ArrayList<EntityHitResult> entitiesHit = new ArrayList<>(this.findHitEntities(initialPosition, blockHitResult.getLocation()));
|
||||
@@ -309,7 +309,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
this.setPos(nextLocation);
|
||||
this.applyEffectsFromBlocks(initialPosition, nextLocation);
|
||||
if (this.portalProcess != null && this.portalProcess.isInsidePortalThisTick()) {
|
||||
- this.handlePortal();
|
||||
+ if (this.handlePortal()) return true; // Luminol - Correct portal logic of some projectile entities (Should not be ticking anymore after portal logics)
|
||||
}
|
||||
|
||||
if (entitiesHit.isEmpty()) {
|
||||
@@ -327,6 +327,7 @@ public abstract class AbstractArrow extends Projectile {
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ return false; // Luminol - Correct portal logic of some projectile entities
|
||||
}
|
||||
|
||||
private ProjectileDeflection hitTargetsOrDeflectSelf(final Collection<EntityHitResult> entityHitResults) {
|
||||
+388
@@ -0,0 +1,388 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 18:54:50 +0800
|
||||
Subject: [PATCH] Configurable region format framework
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
index a814512fcfb85312474ae2c2c21443843bf57831..2e084a5b28cbe4737f48c25e10af589213525362 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
@@ -8,9 +8,9 @@ public interface ChunkSystemRegionFileStorage {
|
||||
|
||||
public boolean moonrise$doesRegionFileNotExistNoIO(final int chunkX, final int chunkZ);
|
||||
|
||||
- public RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ);
|
||||
+ public abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // Luminol - Configurable region file format
|
||||
|
||||
- public RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException;
|
||||
+ public abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // Luminol - Configurable region file format
|
||||
|
||||
public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(
|
||||
final int chunkX, final int chunkZ, final CompoundTag compound
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
index 3bb9b58ee97464687e348e23b99159226415c267..fc264727141c3897e6c06819b9713d4f6395baf0 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
@@ -1273,7 +1273,7 @@ public final class MoonriseRegionFileIO {
|
||||
this.regionDataController.finishWrite(this.chunkX, this.chunkZ, writeData);
|
||||
// Paper start - flush regionfiles on save
|
||||
if (this.world.paperConfig().chunks.flushRegionsOnSave) {
|
||||
- final RegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ);
|
||||
+ final abomination.IRegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ); // Luminol - Add configurable region file
|
||||
if (regionFile != null) {
|
||||
regionFile.flush();
|
||||
} // else: evicted from cache, which should have called flush
|
||||
@@ -1489,7 +1489,7 @@ public final class MoonriseRegionFileIO {
|
||||
|
||||
public static interface IORunnable {
|
||||
|
||||
- public void run(final RegionFile regionFile) throws IOException;
|
||||
+ public void run(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
|
||||
|
||||
}
|
||||
}
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d5815c8c1 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
@@ -8,5 +8,5 @@ public interface ChunkSystemChunkBuffer {
|
||||
|
||||
public void moonrise$setWriteOnClose(final boolean value);
|
||||
|
||||
- public void moonrise$write(final RegionFile regionFile) throws IOException;
|
||||
+ public void moonrise$write(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index a49c46eb7df50fc3c5587a2c3668ab6edc887107..83b9aab16124ddcc416f7b4cd95084e1c64fe5b7 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -986,10 +986,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
if (flush) {
|
||||
for (ServerLevel level : this.getAllLevels()) {
|
||||
String storageName = level.getChunkSource().chunkMap.getStorageName();
|
||||
- LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", LEGACY_WORLD_NAMES_FOR_REALMS_LOG.getOrDefault(storageName, storageName));
|
||||
+ LOGGER.info("ThreadedChunkStorage ({}): All chunks are saved", LEGACY_WORLD_NAMES_FOR_REALMS_LOG.getOrDefault(storageName, storageName)); // Luminol - configurable region format
|
||||
}
|
||||
|
||||
- LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved");
|
||||
+ LOGGER.info("ThreadedChunkStorage: All dimensions are saved"); // Luminol - configurable region format
|
||||
}
|
||||
|
||||
return result;
|
||||
diff --git a/net/minecraft/util/worldupdate/FileToUpgrade.java b/net/minecraft/util/worldupdate/FileToUpgrade.java
|
||||
index a7f2cfa9277c898038f6b9e0a3401db51012b64c..db4dba8849eb27f8f84acc3297e342da4700d839 100644
|
||||
--- a/net/minecraft/util/worldupdate/FileToUpgrade.java
|
||||
+++ b/net/minecraft/util/worldupdate/FileToUpgrade.java
|
||||
@@ -4,5 +4,5 @@ import java.util.List;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.storage.RegionFile;
|
||||
|
||||
-public record FileToUpgrade(RegionFile file, List<ChunkPos> chunksToUpgrade) {
|
||||
+public record FileToUpgrade(abomination.IRegionFile file, List<ChunkPos> chunksToUpgrade) { // Luminol - Configurable region file format
|
||||
}
|
||||
diff --git a/net/minecraft/util/worldupdate/RegionStorageUpgrader.java b/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
|
||||
index b228cd6c54e8c8998923ab332882d99092769c67..140ef4959fa2fe5b9cd251955c93683e8e69d5ba 100644
|
||||
--- a/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
|
||||
+++ b/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
|
||||
@@ -36,7 +36,7 @@ import org.slf4j.Logger;
|
||||
public class RegionStorageUpgrader {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final String NEW_DIRECTORY_PREFIX = "new_";
|
||||
- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
|
||||
+ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\." + me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getArgument() + "$"); // Luminol - Configurable region file format
|
||||
private final DataFixer dataFixer;
|
||||
private final UpgradeProgress upgradeProgress;
|
||||
private final String type;
|
||||
@@ -176,7 +176,8 @@ public class RegionStorageUpgrader {
|
||||
int zOffset = Integer.parseInt(regex.group(2)) << 5;
|
||||
List<ChunkPos> chunkPositions = Lists.newArrayList();
|
||||
|
||||
- try (RegionFile regionSource = new RegionFile(info, regionFile.toPath(), regionFolder, true)) {
|
||||
+ var regionFileInfo = new me.earthme.luminol.utils.RegionCreatorInfo(info, regionFile.toPath(), regionFolder, true); // Luminol - Configurable region file format
|
||||
+ try (abomination.IRegionFile regionSource = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getCreator().create(regionFileInfo)) { // Luminol - Configurable region file format
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
ChunkPos pos = new ChunkPos(x + xOffset, z + zOffset);
|
||||
@@ -253,7 +254,7 @@ public class RegionStorageUpgrader {
|
||||
return storage.upgradeChunkTag(chunkTag, this.defaultVersion, this.dataFixContextTag, targetVersion);
|
||||
}
|
||||
|
||||
- private void onFileFinished(final RegionFile regionFile) {
|
||||
+ private void onFileFinished(final abomination.IRegionFile regionFile) { // Luminol - Configurable region file format
|
||||
if (this.recreateRegionFiles) {
|
||||
if (this.previousWriteFuture != null) {
|
||||
this.previousWriteFuture.join();
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93addb767392 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
|
||||
+public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile , abomination.IRegionFile{ // Paper - rewrite chunk system // Luminol - Configurable region file format
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
|
||||
private static final int SECTOR_BYTES = 4096;
|
||||
@@ -130,7 +130,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
return this.recalculateCount.get();
|
||||
}
|
||||
|
||||
- boolean recalculateHeader() throws IOException {
|
||||
+ public boolean recalculateHeader() throws IOException { // Luminol - Configurable region file format
|
||||
if (!this.canRecalcHeader) {
|
||||
return false;
|
||||
}
|
||||
@@ -789,7 +789,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
}
|
||||
|
||||
- protected synchronized void write(final ChunkPos pos, final ByteBuffer data) throws IOException {
|
||||
+ public synchronized void write(final ChunkPos pos, final ByteBuffer data) throws IOException { // Luminol - Configurable region file format
|
||||
int offsetIndex = getOffsetIndex(pos);
|
||||
int offset = this.offsets.get(offsetIndex);
|
||||
int sectorNumber = getSectorNumber(offset);
|
||||
@@ -907,7 +907,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
|
||||
@Override
|
||||
- public final void moonrise$write(final RegionFile regionFile) throws IOException {
|
||||
+ public final void moonrise$write(final abomination.IRegionFile regionFile) throws IOException { // Luminol - Configurable region file format
|
||||
regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count));
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
@@ -973,11 +973,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
return (x & 31) + (z & 31) * 32;
|
||||
}
|
||||
|
||||
- synchronized boolean isOversized(int x, int z) {
|
||||
+ public synchronized boolean isOversized(int x, int z) { // Luminol - Configurable region file format
|
||||
return this.oversized[getChunkIndex(x, z)] == 1;
|
||||
}
|
||||
|
||||
- synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
|
||||
+ public synchronized void setOversized(int x, int z, boolean oversized) throws IOException { // Luminol - Configurable region file format
|
||||
final int offset = getChunkIndex(x, z);
|
||||
boolean previous = this.oversized[offset] == 1;
|
||||
this.oversized[offset] = (byte) (oversized ? 1 : 0);
|
||||
@@ -1016,7 +1016,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt");
|
||||
}
|
||||
|
||||
- synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException {
|
||||
+ public synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException { // Luminol - Configurable region file format
|
||||
Path file = getOversizedFile(x, z);
|
||||
try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new java.util.zip.InflaterInputStream(Files.newInputStream(file))))) {
|
||||
return net.minecraft.nbt.NbtIo.read((java.io.DataInput) out);
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977ebfb18517 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -19,7 +19,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
|
||||
public static final String ANVIL_EXTENSION = ".mca";
|
||||
private static final int MAX_CACHE_SIZE = 256;
|
||||
- private final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>();
|
||||
+ private final Long2ObjectLinkedOpenHashMap<abomination.IRegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>(); // Luminol - Configurable region file format
|
||||
private final RegionStorageInfo info;
|
||||
private final Path folder;
|
||||
private final boolean sync;
|
||||
@@ -30,7 +30,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@Nullable
|
||||
public static ChunkPos getRegionFileCoordinates(Path file) {
|
||||
String fileName = file.getFileName().toString();
|
||||
- if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) {
|
||||
+ if (!fileName.startsWith("r.") || !fileName.endsWith(getExtensionName())) { // Luminol - Configurable region file format
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -55,8 +55,32 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
private static final int MAX_NON_EXISTING_CACHE = 1024 * 4;
|
||||
private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
|
||||
private static String getRegionFileName(final int chunkX, final int chunkZ) {
|
||||
- return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".mca";
|
||||
+ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + getExtensionName(); // Luminol - Configurable region file format
|
||||
}
|
||||
+ // Luminol start - Configurable region file format
|
||||
+ public static abomination.IRegionFile createNew(RegionStorageInfo info, Path filePath, Path folder, boolean sync) throws IOException{
|
||||
+ final me.earthme.luminol.enums.EnumRegionFormat regionFormat = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat;
|
||||
+ final String fullFileName = filePath.getFileName().toString();
|
||||
+ final String[] fullNameSplit = fullFileName.split("\\.");
|
||||
+ final String extensionName = fullNameSplit[fullNameSplit.length - 1];
|
||||
+
|
||||
+ if (!regionFormat.getArgument().equalsIgnoreCase(extensionName)) {
|
||||
+ // delayed crash
|
||||
+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(() -> {
|
||||
+ new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
|
||||
+ });
|
||||
+
|
||||
+
|
||||
+ throw new IOException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
|
||||
+ }
|
||||
+
|
||||
+ return regionFormat.getCreator().create(new me.earthme.luminol.utils.RegionCreatorInfo(info, filePath, folder, sync));
|
||||
+ }
|
||||
+
|
||||
+ public static String getExtensionName() {
|
||||
+ return "." + me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getArgument();
|
||||
+ }
|
||||
+ // Luminol end
|
||||
|
||||
private boolean doesRegionFilePossiblyExist(final long position) {
|
||||
synchronized (this.nonExistingRegionFiles) {
|
||||
@@ -90,15 +114,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
|
||||
@Override
|
||||
- public synchronized final RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) {
|
||||
+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // Luminol - Configurable region file format
|
||||
return this.regionCache.getAndMoveToFirst(ChunkPos.pack(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT));
|
||||
}
|
||||
|
||||
@Override
|
||||
- public synchronized final RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException {
|
||||
+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // Luminol - Configurable region file format
|
||||
final long key = ChunkPos.pack(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
|
||||
|
||||
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
|
||||
+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
@@ -124,7 +148,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
FileUtil.createDirectoriesSafe(this.folder);
|
||||
|
||||
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
|
||||
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
|
||||
|
||||
this.regionCache.putAndMoveToFirst(key, ret);
|
||||
|
||||
@@ -143,7 +167,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
|
||||
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
- final RegionFile regionFile = this.getRegionFile(pos);
|
||||
+ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
|
||||
|
||||
// note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
|
||||
// (and, the regionfile parameter is unused for writing until the write call)
|
||||
@@ -177,7 +201,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
) throws IOException {
|
||||
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
|
||||
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
|
||||
+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
|
||||
if (regionFile != null) {
|
||||
regionFile.clear(pos);
|
||||
} // else: didn't exist
|
||||
@@ -192,7 +216,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.ReadData moonrise$readData(
|
||||
final int chunkX, final int chunkZ
|
||||
) throws IOException {
|
||||
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
|
||||
+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
|
||||
|
||||
final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
|
||||
|
||||
@@ -237,7 +261,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
final ChunkPos headerChunkPos = SerializableChunkData.getChunkCoordinate(ret);
|
||||
- final RegionFile regionFile = this.getRegionFile(pos);
|
||||
+ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
|
||||
|
||||
if (regionFile.getRecalculateCount() != readData.recalculateCount()) {
|
||||
return null;
|
||||
@@ -261,7 +285,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
// Paper start - rewrite chunk system
|
||||
- public RegionFile getRegionFile(ChunkPos pos) throws IOException {
|
||||
+ public abomination.IRegionFile getRegionFile(ChunkPos pos) throws IOException { // Luminol - Configurable region file format
|
||||
return this.getRegionFile(pos, false);
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
@@ -273,7 +297,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
this.isChunkData = info.dfuType()[0] == net.minecraft.util.datafix.DataFixTypes.CHUNK; // Paper - recalculate region file headers
|
||||
}
|
||||
|
||||
- @org.jetbrains.annotations.Contract("_, false -> !null") private @Nullable RegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit
|
||||
+ @org.jetbrains.annotations.Contract("_, false -> !null") private abomination.@Nullable IRegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit // Luminol - Configurable region file format
|
||||
// Paper start - rewrite chunk system
|
||||
if (existingOnly) {
|
||||
return this.moonrise$getRegionFileIfExists(pos.x(), pos.z());
|
||||
@@ -281,7 +305,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
synchronized (this) {
|
||||
final long key = ChunkPos.pack(pos.x() >> REGION_SHIFT, pos.z() >> REGION_SHIFT);
|
||||
|
||||
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
|
||||
+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
@@ -298,7 +322,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
FileUtil.createDirectoriesSafe(this.folder);
|
||||
|
||||
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
|
||||
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
|
||||
|
||||
this.regionCache.putAndMoveToFirst(key, ret);
|
||||
|
||||
@@ -312,7 +336,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4);
|
||||
}
|
||||
|
||||
- private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
|
||||
+ private static CompoundTag readOversizedChunk(abomination.IRegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // Luminol - Configurable region file format
|
||||
synchronized (regionfile) {
|
||||
try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
|
||||
CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x(), chunkCoordinate.z());
|
||||
@@ -346,7 +370,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
public @Nullable CompoundTag read(final ChunkPos pos) throws IOException {
|
||||
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
|
||||
- RegionFile region = this.getRegionFile(pos, true);
|
||||
+ abomination.IRegionFile region = this.getRegionFile(pos, true); // Luminol - Configurable region file format
|
||||
if (region == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -383,7 +407,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
public void scanChunk(final ChunkPos pos, final StreamTagVisitor scanner) throws IOException {
|
||||
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
|
||||
- RegionFile region = this.getRegionFile(pos, true);
|
||||
+ abomination.IRegionFile region = this.getRegionFile(pos, true); // Luminol - Configurable region file format
|
||||
if (region == null) {
|
||||
return;
|
||||
}
|
||||
@@ -398,7 +422,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
public void write(final ChunkPos pos, final @Nullable CompoundTag value) throws IOException {
|
||||
if (!SharedConstants.DEBUG_DONT_SAVE_WORLD) {
|
||||
- RegionFile region = this.getRegionFile(pos, value == null); // CraftBukkit // Paper - rewrite chunk system
|
||||
+ abomination.IRegionFile region = this.getRegionFile(pos, value == null); // CraftBukkit // Paper - rewrite chunk system // Luminol - Configurable region file format
|
||||
// Paper start - rewrite chunk system
|
||||
if (region == null) {
|
||||
// if the RegionFile doesn't exist, no point in deleting from it
|
||||
@@ -430,7 +454,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper start - rewrite chunk system
|
||||
synchronized (this) {
|
||||
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
|
||||
- for (final RegionFile regionFile : this.regionCache.values()) {
|
||||
+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
|
||||
try {
|
||||
regionFile.close();
|
||||
} catch (final IOException ex) {
|
||||
@@ -446,7 +470,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper start - rewrite chunk system
|
||||
synchronized (this) {
|
||||
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
|
||||
- for (final RegionFile regionFile : this.regionCache.values()) {
|
||||
+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
|
||||
try {
|
||||
regionFile.flush();
|
||||
} catch (final IOException ex) {
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:00:48 +0800
|
||||
Subject: [PATCH] Do not enable any debug subscriptions
|
||||
|
||||
Really this would really crash the server by accident when the operators used F3 + J or toggled the debug synchronizer
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 44b3dfbf529630d8cca9a4270ae2a7c94c5a077c..34cc36f6bdf435593d16f2e7af280a27be048280 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -3504,7 +3504,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
|
||||
public Set<DebugSubscription<?>> debugSubscriptions() {
|
||||
- return !this.server.debugSubscribers().hasRequiredPermissions(this) ? Set.of() : this.requestedDebugSubscriptions;
|
||||
+ // return !this.server.debugSubscribers().hasRequiredPermissions(this) ? Set.of() : this.requestedDebugSubscriptions; // Luminol - Do not enable any debug subscriptions
|
||||
+ return Set.of(); // Luminol - Do not enable any debug subscriptions
|
||||
}
|
||||
|
||||
public record RespawnConfig(LevelData.RespawnData respawnData, boolean forced) {
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:25:45 +0800
|
||||
Subject: [PATCH] Do not load too far poi chunk in poi compete scan
|
||||
|
||||
Beeeeeeeeeeeeeeee
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java b/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java
|
||||
index 53131c1b8d5562f9a1b45dfab4fdbdd37b655139..0e9c19a820aefa802d6df134b21f5128a5e8d656 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java
|
||||
@@ -24,8 +24,18 @@ public class PoiCompetitorScan {
|
||||
return true;
|
||||
}
|
||||
// Folia end - region threading
|
||||
- level.getPoiManager()
|
||||
- .getType(pos.pos())
|
||||
+ // Luminol start - POI fixes
|
||||
+ var blockPosOfJobSite = pos.pos();
|
||||
+ var sectionPosOfJobSite = net.minecraft.core.SectionPos.asLong(blockPosOfJobSite);
|
||||
+ var poiManager = level.getPoiManager();
|
||||
+ // we don't care if we should clear the memory of JOB_SITE
|
||||
+ // as it will be automatically removed in SetWalkTargetFromBlockMemory
|
||||
+ // so simply break down if it's not loaded
|
||||
+ var poiChunk = me.earthme.luminol.config.modules.fixes.POIRangeFixes.doNotCompetePOIIfUnloaded ? poiManager.get(sectionPosOfJobSite) : poiManager.getOrLoad(sectionPosOfJobSite);
|
||||
+ poiChunk.flatMap(poiSection -> poiSection.getType(blockPosOfJobSite))
|
||||
+ // Luminol end - POI fixes
|
||||
+ /*level.getPoiManager() // Luminol - POI fixes
|
||||
+ .getType(pos.pos())*/ // Luminol - POI fixes
|
||||
.ifPresent(
|
||||
// Paper start - Improve performance of PoiCompetitorScan by unrolling stream
|
||||
// The previous logic used Stream#reduce to simulate a form of single-iteration bubble sort
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:02:01 +0800
|
||||
Subject: [PATCH] Fixes around entity brain and memories
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 3b1c3e84ab24b6e3a0e4d129b3617b393b6d6651..9c8e8de53cbbd87ac7cb8483bd3c1af3fcf66b6e 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -299,6 +299,11 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
if (Objects.equals(currentTarget, target)) {
|
||||
return false;
|
||||
}
|
||||
+ // Luminol start - Fix off-region targeting
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(target)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
LivingEntity originalTarget = target;
|
||||
target = asValidTarget(target);
|
||||
if (reason != null) {
|
||||
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
|
||||
index e097bc1268b4050e3948413c52dea69950858458..27894e2935e2afee8190708def4be3b00f922f64 100644
|
||||
--- a/net/minecraft/world/entity/ai/Brain.java
|
||||
+++ b/net/minecraft/world/entity/ai/Brain.java
|
||||
@@ -383,7 +383,7 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
|
||||
public void tick(final ServerLevel level, final E body) {
|
||||
- this.forgetOutdatedMemories();
|
||||
+ this.forgetOutdatedMemories(body); // Luminol - Add config to force clean entity memory that don't belong to current tick region
|
||||
this.tickSensors(level, body);
|
||||
this.startEachNonRunningBehavior(level, body);
|
||||
this.tickEachRunningBehavior(level, body);
|
||||
@@ -395,8 +395,8 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
- private void forgetOutdatedMemories() {
|
||||
- this.memories.values().forEach(MemorySlot::tick);
|
||||
+ private void forgetOutdatedMemories(E body) { // Luminol - Add config to force clean entity memory that don't belong to current tick region
|
||||
+ this.memories.values().forEach(slot -> slot.tick(body)); // Luminol - Add config to force clean entity memory that don't belong to current tick region
|
||||
}
|
||||
|
||||
public void stopAll(final ServerLevel level, final E body) {
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
index f744ecd20dc70786311a7162b52aa4ceca0717db..aa60fbfbe7283f1ed9cf5343d59d1222380857dd 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java
|
||||
@@ -81,6 +81,11 @@ public class BehaviorUtils {
|
||||
public static void setWalkAndLookTargetMemories(
|
||||
final LivingEntity walker, final PositionTracker target, final float speedModifier, final int closeEnoughDistance
|
||||
) {
|
||||
+ // Luminol - Do not set walk target if target position is out of current tick region
|
||||
+ if (!target.checkThread(walker.level())) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
WalkTarget walkTarget = new WalkTarget(target, speedModifier, closeEnoughDistance);
|
||||
walker.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, target);
|
||||
walker.getBrain().setMemory(MemoryModuleType.WALK_TARGET, walkTarget);
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/BlockPosTracker.java b/net/minecraft/world/entity/ai/behavior/BlockPosTracker.java
|
||||
index 68251875edfa47ac34c64f99510998ad4bbb14b4..d83b353395bad7c6c41dfaa24018fd207904d995 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/BlockPosTracker.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/BlockPosTracker.java
|
||||
@@ -37,4 +37,11 @@ public class BlockPosTracker implements PositionTracker {
|
||||
public String toString() {
|
||||
return "BlockPosTracker{blockPos=" + this.blockPos + ", centerPosition=" + this.centerPosition + "}";
|
||||
}
|
||||
+
|
||||
+ // Luminol start - Fix a series issue around entity memory typed GlobalPos and WalkTarget
|
||||
+ @Override
|
||||
+ public boolean checkThread(net.minecraft.world.level.Level currOwnedByLevel) {
|
||||
+ return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(currOwnedByLevel, this.blockPos);
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/EntityTracker.java b/net/minecraft/world/entity/ai/behavior/EntityTracker.java
|
||||
index 3ac52b025ac3e1a3f9135b8e593a385a847afe0f..29c13f18cff52e9950e8932c75cb12fb02f952cb 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/EntityTracker.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/EntityTracker.java
|
||||
@@ -55,4 +55,11 @@ public class EntityTracker implements PositionTracker {
|
||||
public String toString() {
|
||||
return "EntityTracker for " + this.entity;
|
||||
}
|
||||
+
|
||||
+ // Luminol start - Fix a series issue around entity memory typed GlobalPos and WalkTarget
|
||||
+ @Override
|
||||
+ public boolean checkThread(net.minecraft.world.level.Level currOwnedByLevel) {
|
||||
+ return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.entity);
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/PositionTracker.java b/net/minecraft/world/entity/ai/behavior/PositionTracker.java
|
||||
index ce6cf5ecfb190428e3ef9b7dd39c98e3d27a7b9d..3334da2236fbe90cbdc3e67884f9c6ed80ac0f56 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/PositionTracker.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/PositionTracker.java
|
||||
@@ -10,4 +10,7 @@ public interface PositionTracker {
|
||||
BlockPos currentBlockPosition();
|
||||
|
||||
boolean isVisibleBy(final LivingEntity body);
|
||||
+
|
||||
+
|
||||
+ boolean checkThread(net.minecraft.world.level.Level currOwnedByLevel); // Luminol - Fix a series issue around entity memory typed GlobalPos and WalkTarget
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/SleepInBed.java b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
index 16017d819c28b077f732e2ef571eac179d24e323..7a598aa1a0963fda3302946a30d0330c341da74f 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
|
||||
@@ -57,6 +57,11 @@ public class SleepInBed extends Behavior<LivingEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol Start - Prevent off-tick-region chunk operations
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(level, target.pos())) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol End
|
||||
BlockState blockState = level.getBlockStateIfLoaded(target.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 target.pos().closerToCenterThan(body.position(), 2.0) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED);
|
||||
diff --git a/net/minecraft/world/entity/ai/memory/MemorySlot.java b/net/minecraft/world/entity/ai/memory/MemorySlot.java
|
||||
index 88a89b4c72cc99dc89d3f3cc928b2dfda4125759..3b51a44ab700740047c9e725547ceec65c0c80b1 100644
|
||||
--- a/net/minecraft/world/entity/ai/memory/MemorySlot.java
|
||||
+++ b/net/minecraft/world/entity/ai/memory/MemorySlot.java
|
||||
@@ -13,7 +13,7 @@ public class MemorySlot<T> {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
- public void tick() {
|
||||
+ public void tick(net.minecraft.world.entity.Entity owner) { // Luminol - Add config to force clean entity memory that don't belong to current tick region
|
||||
if (this.hasValue() && this.canExpire()) {
|
||||
if (this.hasExpired()) {
|
||||
this.clear();
|
||||
@@ -21,6 +21,41 @@ public class MemorySlot<T> {
|
||||
this.timeToLive--;
|
||||
}
|
||||
}
|
||||
+ // Luminol start - Add config to force clean entity memory that don't belong to current tick region
|
||||
+ final net.minecraft.world.level.Level ownerLevel = owner.level();
|
||||
+
|
||||
+ // type: entity
|
||||
+ if (me.earthme.luminol.config.modules.fixes.ForceCleanupEntityBrainMemoryConfig.enabledForEntity && this.value instanceof net.minecraft.world.entity.Entity entity) {
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
|
||||
+ this.clear();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // type: block_pos
|
||||
+ if (me.earthme.luminol.config.modules.fixes.ForceCleanupEntityBrainMemoryConfig.enabledForBlockPos && this.value instanceof net.minecraft.core.BlockPos blockPos) {
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(ownerLevel, blockPos)) {
|
||||
+ this.clear();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ //type: position_tracker and walk_target
|
||||
+ if (me.earthme.luminol.config.modules.fixes.ForceCleanupEntityBrainMemoryConfig.enabledForPositionTracker) {
|
||||
+ net.minecraft.world.entity.ai.behavior.PositionTracker tracker = null;
|
||||
+
|
||||
+ if (value instanceof net.minecraft.world.entity.ai.behavior.PositionTracker positionTracker) {
|
||||
+ tracker = positionTracker;
|
||||
+ }
|
||||
+
|
||||
+ if (value instanceof net.minecraft.world.entity.ai.memory.WalkTarget walkTarget) {
|
||||
+ tracker = walkTarget.getTarget();
|
||||
+ }
|
||||
+
|
||||
+ if (tracker != null && !tracker.checkThread(owner.level())) {
|
||||
+ this.clear();
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
public static <T> MemorySlot<T> create() {
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
index e44814cfb6afb594456b8215bd13a92e93de2c85..c18e2071c699d9c5f4d46b7a58191df4f4d8ab5d 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
@@ -60,6 +60,17 @@ public class FlyingPathNavigation extends PathNavigation {
|
||||
|
||||
if (!this.isDone()) {
|
||||
Vec3 target = this.path.getNextEntityPos(this.mob);
|
||||
+ // Luminol - Recompute path when path finding out of current tick region
|
||||
+ if (me.earthme.luminol.config.modules.fixes.PathfindingFixesConfig.breakDownPathfindingWhenOutOfRegion) {
|
||||
+ // we assume that:
|
||||
+ // 1. The code above doesn't touch the 'main thread context' with the position from 'this.path'
|
||||
+ // 2. The pathfinder could correctly recompute or discard the incorrect target position and this situation is happening rarely
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.mob.level(), target)) {
|
||||
+ this.hasDelayedRecomputation = true;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
this.mob.getMoveControl().setWantedPosition(target.x, target.y, target.z, this.speedModifier);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
index 2ea1ec39a37899ae1510d0036aa670e758077537..4c727e4f224f6a31a4cd9d024bdcfaf0fa1bc0e5 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -188,6 +188,18 @@ public abstract class PathNavigation {
|
||||
}
|
||||
}
|
||||
// Paper end - EntityPathfindEvent
|
||||
+ // Luminol start - Do not path find for targets out of current region
|
||||
+ if (me.earthme.luminol.config.modules.fixes.PathfindingFixesConfig.doNotPathfindToNotOwnedTargets) {
|
||||
+ // filter the targets not owned by current region
|
||||
+ targets = new java.util.HashSet<>(targets); // well no idea about how to determine if this should be copied to a modifiable one
|
||||
+ targets.removeIf(pos -> !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.mob.level(), pos));
|
||||
+
|
||||
+ // return if no available (observe the logic in the first if block)
|
||||
+ if (targets.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("pathfind");
|
||||
BlockPos fromPos = above ? this.mob.blockPosition().above() : this.mob.blockPosition();
|
||||
@@ -286,6 +298,17 @@ public abstract class PathNavigation {
|
||||
|
||||
if (!this.isDone()) {
|
||||
Vec3 target = this.path.getNextEntityPos(this.mob);
|
||||
+ // Luminol - Recompute path when path finding out of current tick region
|
||||
+ if (me.earthme.luminol.config.modules.fixes.PathfindingFixesConfig.breakDownPathfindingWhenOutOfRegion) {
|
||||
+ // we assume that:
|
||||
+ // 1. The code above doesn't touch the 'main thread context' with the position from 'this.path'
|
||||
+ // 2. The pathfinder could correctly recompute or discard the incorrect target position and this situation is happening rarely
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.mob.level(), target)) {
|
||||
+ this.hasDelayedRecomputation = true;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
this.mob.getMoveControl().setWantedPosition(target.x, this.getGroundY(target), target.z, this.speedModifier);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/allay/AllayAi.java b/net/minecraft/world/entity/animal/allay/AllayAi.java
|
||||
index c3667e7997551e0f5ce63bc6ee890082d1431400..2e2458535a8ec542d6371ceba2fff1260773c7f5 100644
|
||||
--- a/net/minecraft/world/entity/animal/allay/AllayAi.java
|
||||
+++ b/net/minecraft/world/entity/animal/allay/AllayAi.java
|
||||
@@ -112,6 +112,17 @@ public class AllayAi {
|
||||
Optional<GlobalPos> likedNoteblockPos = brain.getMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION);
|
||||
if (likedNoteblockPos.isPresent()) {
|
||||
GlobalPos position = likedNoteblockPos.get();
|
||||
+ // Luminol start - Do not like item if they were out of current tickregion
|
||||
+ final Level targetLevel = allay.level().getServer().getLevel(position.dimension());
|
||||
+ final BlockPos targetPos = position.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(allay, brain, position)) {
|
||||
return Optional.of(new BlockPosTracker(position.pos().above()));
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
index d5394ae7ce56555ad21aeafb2d78c291c62e2988..a2873d8bbfa3e04678bc31637222b3a10cd6fedd 100644
|
||||
--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
+++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java
|
||||
@@ -279,8 +279,18 @@ public class Sniffer extends Animal {
|
||||
|
||||
private boolean canDig(final BlockPos position) {
|
||||
return this.level().getBlockState(position).is(BlockTags.SNIFFER_DIGGABLE_BLOCK)
|
||||
- && this.getExploredPositions().noneMatch(explored -> GlobalPos.of(this.level().dimension(), position).equals(explored))
|
||||
- && Optional.ofNullable(this.getNavigation().createPath(position, 1)).map(Path::canReach).orElse(false);
|
||||
+ && this.getExploredPositions().noneMatch(explored -> { // Luminol start - Do not pathfind out of tickregion
|
||||
+ // thread checks
|
||||
+ final Level targetLevel = net.minecraft.server.MinecraftServer.getServer().getLevel(explored.dimension());
|
||||
+ final BlockPos targetPos = explored.pos();
|
||||
+
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(targetLevel, targetPos)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return GlobalPos.of(this.level().dimension(), position).equals(explored); // Original logic
|
||||
+ }) // Luminol end
|
||||
+ && Optional.ofNullable(this.getNavigation().createPath(position, 1)).map(Path::canReach).orElse(false); // Luminol - Do not pathfind out of tickregion - diff on change
|
||||
}
|
||||
|
||||
private void dropSeed() {
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:16:45 +0800
|
||||
Subject: [PATCH] Fix off region leashing
|
||||
|
||||
PS: My friend reported me this bug and I still need to check the details of how the bug was caused
|
||||
|
||||
XD
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Leashable.java b/net/minecraft/world/entity/Leashable.java
|
||||
index 98034a4c96bf2972316078d3b3a49140921aab50..284ba0c3742d5d5ab0b344a84a9c8e2c2a98a74a 100644
|
||||
--- a/net/minecraft/world/entity/Leashable.java
|
||||
+++ b/net/minecraft/world/entity/Leashable.java
|
||||
@@ -95,10 +95,24 @@ public interface Leashable {
|
||||
if (leashUuid.isPresent()) {
|
||||
Entity leasher = serverLevel.getEntity(leashUuid.get());
|
||||
if (leasher != null) {
|
||||
+ // Luminol start - Fix off region leashing
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(leasher)) {
|
||||
+ entity.spawnAtLocation(serverLevel, Items.LEAD);
|
||||
+ entity.setLeashData(null);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
setLeashedTo(entity, leasher, true);
|
||||
return;
|
||||
}
|
||||
} else if (pos.isPresent()) {
|
||||
+ // Luminol start - Fix off region leashing
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(serverLevel, pos.get())) {
|
||||
+ entity.spawnAtLocation(serverLevel, Items.LEAD);
|
||||
+ entity.setLeashData(null);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
setLeashedTo(entity, LeashFenceKnotEntity.getOrCreateKnot(serverLevel, pos.get()), true);
|
||||
return;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:21:30 +0800
|
||||
Subject: [PATCH] Fix unpatched task returning of
|
||||
ServerConfigurationPacketListenerImpl#disconnectAsync
|
||||
|
||||
Inspired by https://github.com/CraftCanvasMC/Canvas/blob/ver/1.21.8/canvas-server/minecraft-patches/sources/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch
|
||||
but Canvas loses its main thread checks so fixed that btw
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
index 40b4eeb561a91264b9ab6ddc49cb8a93daae84a4..97f4c546663fb19558246366a3d8d77f2b9327ef 100644
|
||||
--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
@@ -290,13 +290,14 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
|
||||
// Paper start
|
||||
@Override
|
||||
public void disconnectAsync(final net.minecraft.network.DisconnectionDetails disconnectionInfo) {
|
||||
- if (this.cserver.isPrimaryThread()) {
|
||||
+ if (io.papermc.paper.threadedregions.RegionizedServer.isGlobalTickThread()) { // Luminol - Fix unpatched task returning of ServerConfigurationPacketListenerImpl#disconnectAsync
|
||||
this.disconnect(disconnectionInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
this.connection.setReadOnly();
|
||||
- this.server.scheduleOnMain(() -> {
|
||||
+ // this.server.scheduleOnMain(() -> { // Luminol - Fix unpatched task returning of ServerConfigurationPacketListenerImpl#disconnectAsync
|
||||
+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(() -> { // Luminol - Fix unpatched task returning of ServerConfigurationPacketListenerImpl#disconnectAsync
|
||||
this.disconnect(disconnectionInfo); // Currently you cannot cancel disconnect during the config stage
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 23:24:07 +0800
|
||||
Subject: [PATCH] Fix riding statistics desync
|
||||
|
||||
Referred to: https://github.com/CraftCanvasMC/Canvas/commit/057175b0c10d5a4d1d9059fd9d077750c32633b2
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 34cc36f6bdf435593d16f2e7af280a27be048280..98d1ab3aa8dfbe571371d01544da2750339ce988 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -2537,7 +2537,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
}
|
||||
}
|
||||
|
||||
- private void checkRidingStatistics(final double dx, final double dy, final double dz) {
|
||||
+ public void checkRidingStatistics(final double dx, final double dy, final double dz) { // Luminol - Fix riding statics desync (make public)
|
||||
if (this.isPassenger() && !didNotMove(dx, dy, dz)) {
|
||||
int distance = Math.round((float)Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F);
|
||||
Entity vehicle = this.getVehicle();
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index a2b57f62b745dd21e215f919d335f14f5cb1706f..2cf8bdf6c4ab04ab42829b7af5eb89e6bd509d7a 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4198,7 +4198,13 @@ public abstract class Entity
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol start - Fix riding statics desync
|
||||
public void adjustRiders(boolean teleport) {
|
||||
+ this.adjustRiders(teleport, false);
|
||||
+ }
|
||||
+
|
||||
+ public void adjustRiders(boolean teleport, boolean syncStatics) {
|
||||
+ // Luminol end - Fix riding statics desync
|
||||
java.util.ArrayDeque<EntityTreeNode> queue = new java.util.ArrayDeque<>();
|
||||
queue.add(this);
|
||||
|
||||
@@ -4211,14 +4217,24 @@ public abstract class Entity
|
||||
|
||||
for (EntityTreeNode passenger : passengers) {
|
||||
queue.add(passenger);
|
||||
+ // Luminol start - Fix riding statics desync
|
||||
+ final double oldX = passenger.root.getX();
|
||||
+ final double oldY = passenger.root.getY();
|
||||
+ final double oldZ = passenger.root.getZ();
|
||||
+ // Luminol end - Fix riding statics desync
|
||||
curr.root.positionRider(passenger.root, teleport ? Entity::snapTo : Entity::setPos);
|
||||
+ // Luminol start - Fix riding statics desync
|
||||
+ if (syncStatics && passenger.root instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.checkRidingStatistics(serverPlayer.getX() - oldX, serverPlayer.getY() - oldY, serverPlayer.getZ() - oldZ);
|
||||
+ }
|
||||
+ // Luminol end - Fix riding statics desync
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void repositionAllPassengers(boolean teleport) {
|
||||
- this.makePassengerTree().adjustRiders(teleport);
|
||||
+ this.makePassengerTree().adjustRiders(teleport, true); // Luminol - Fix riding statics desync
|
||||
}
|
||||
|
||||
protected EntityTreeNode makePassengerTree() {
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 10:45:19 +0800
|
||||
Subject: [PATCH] Fix misbehaved ender pearls when player switched dimension
|
||||
|
||||
A fix of https://github.com/PaperMC/Folia/issues/421
|
||||
|
||||
Almost the same bug as:
|
||||
https://github.com/PaperMC/Folia/pull/418 and https://github.com/PaperMC/Folia/issues/393
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java
|
||||
index 501a0e89cc7bcfce6793f059b080b38666e0fb64..ad35eafa457f706879ba8a9c92b3a34e620ee2d6 100644
|
||||
--- a/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java
|
||||
+++ b/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java
|
||||
@@ -264,7 +264,8 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
|
||||
int previousChunkZ = SectionPos.blockToSectionCoord(this.position().z());
|
||||
Entity owner = this.owner != null ? findOwnerIncludingDeadPlayer(serverLevel, this.owner.getUUID()) : null;
|
||||
if (owner instanceof ServerPlayer serverPlayer
|
||||
- && !owner.isAlive()
|
||||
+ // && !owner.isAlive() // Luminol - Fix misbehaved ender pearls when player switched dimension
|
||||
+ && (owner.getBukkitEntity().taskScheduler.isRetired() || serverPlayer.getHealth() <= 0.0D) // Luminol - Fix misbehaved ender pearls when player switched dimension
|
||||
&& !serverPlayer.wonGame
|
||||
&& serverPlayer.level().getGameRules().get(GameRules.ENDER_PEARLS_VANISH_ON_DEATH)) {
|
||||
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Thu, 2 Apr 2026 12:26:24 +0800
|
||||
Subject: [PATCH] Fix long commands support
|
||||
|
||||
Some long commands can be run through the dialog command, but paper has prohibited it.
|
||||
Revert to vanilla to fix it.
|
||||
|
||||
diff --git a/net/minecraft/network/protocol/game/ServerboundChatCommandPacket.java b/net/minecraft/network/protocol/game/ServerboundChatCommandPacket.java
|
||||
index 491af2413a4e793a121fec368259ff8211ed031e..042cb4792b0084f143608f05dd08da133a31e435 100644
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundChatCommandPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundChatCommandPacket.java
|
||||
@@ -12,7 +12,7 @@ public record ServerboundChatCommandPacket(String command) implements Packet<Ser
|
||||
);
|
||||
|
||||
private ServerboundChatCommandPacket(final FriendlyByteBuf input) {
|
||||
- this(input.readUtf(MAX_CHAT_PACKET_INPUT_SIZE)); // Paper - limit chat command inputs
|
||||
+ this(me.earthme.luminol.config.modules.fixes.LongCommandSupportConfig.enabled ? input.readUtf() : input.readUtf(MAX_CHAT_PACKET_INPUT_SIZE)); // Paper - limit chat command inputs // Luminol - add support for long command inputs
|
||||
}
|
||||
|
||||
private void write(final FriendlyByteBuf output) {
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 20 Apr 2026 01:02:43 +0800
|
||||
Subject: [PATCH] Fix creative player item pick
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 223793bea54a483fefc66caa7e07b29ab351c339..303b9befb30d7156a9a71900ac1a6ea8f7e8d876 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -420,7 +420,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
Item item = itemStack.getItem();
|
||||
int orgCount = itemStack.getCount();
|
||||
// CraftBukkit start - fire PlayerPickupItemEvent
|
||||
- int canHold = player.getInventory().canHold(itemStack);
|
||||
+ int canHold = player.hasInfiniteMaterials() ? orgCount : player.getInventory().canHold(itemStack); // Luminol - Fix creative item picking
|
||||
int remaining = orgCount - canHold;
|
||||
boolean flyAtPlayer = false; // Paper
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Mon, 20 Apr 2026 01:10:30 +0800
|
||||
Subject: [PATCH] Fix entity portal-teleport speed
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c6434ff2e5c211887c2e98c8462a49e0e1cb5b21..534f103234eb92571c664cbcfea4ce4e990d3ea8 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1492,7 +1492,27 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
foliaProfiler.startTimer(timerId);
|
||||
try {
|
||||
// Folia end - profiler
|
||||
+ // Luminol start - Entity portal-teleport speed fix
|
||||
if (isActive) { // Paper - EAR 2
|
||||
+ if (!(entity instanceof Player) && entity.teleportTickType == 2) { // Luminol - after portal compensate tick
|
||||
+ entity.tick();
|
||||
+ entity.tick();
|
||||
+ entity.teleportTickType = 0;
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (entity.handlePortal()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (!(entity instanceof Player) && entity.teleportTickType == 1) { // Luminol - portal teleport only
|
||||
+ entity.teleportTickType++;
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (entity.handlePortal()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
entity.tick();
|
||||
// Folia start - region threading
|
||||
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) {
|
||||
@@ -1503,6 +1523,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// portalled
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+ // Luminol end - Entity portal-teleport speed fix
|
||||
// Folia end - region threading
|
||||
} else {entity.inactiveTick();} // Paper - EAR 2
|
||||
profiler.pop();
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 2cf8bdf6c4ab04ab42829b7af5eb89e6bd509d7a..a52d5c0ba970d666fd57e075d14350ff07401bac 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -387,6 +387,7 @@ public abstract class Entity
|
||||
public long activatedTick = Integer.MIN_VALUE;
|
||||
public boolean isTemporarilyActive;
|
||||
public long activatedImmunityTick = Integer.MIN_VALUE;
|
||||
+ public int teleportTickType = 0;// Luminol - Entity portal-teleport speed fix
|
||||
|
||||
public void inactiveTick() {
|
||||
}
|
||||
@@ -3595,6 +3596,7 @@ public abstract class Entity
|
||||
} else {
|
||||
if (this.portalProcess == null || !this.portalProcess.isSamePortal(portal)) {
|
||||
this.portalProcess = new PortalProcessor(portal, pos.immutable());
|
||||
+ this.teleportTickType = 1; // Luminol - Entity portal-teleport speed fix
|
||||
} else if (!this.portalProcess.isInsidePortalThisTick()) {
|
||||
this.portalProcess.updateEntryPosition(pos.immutable());
|
||||
this.portalProcess.setAsInsidePortalThisTick(true);
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Wed, 24 Jun 2026 22:52:13 +0800
|
||||
Subject: [PATCH] Fix player auto saving ignores interval
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 98d1ab3aa8dfbe571371d01544da2750339ce988..264de9099b19779f20ad23c41d0967670759ae12 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -208,7 +208,7 @@ import org.slf4j.Logger;
|
||||
|
||||
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- public static final long LAST_SAVE_ABSENT = Long.MIN_VALUE; public long lastSave = LAST_SAVE_ABSENT; // Paper // Folia - threaded regions - changed to nanoTime
|
||||
+ public static final long LAST_SAVE_ABSENT = Long.MIN_VALUE; public long lastSave = System.nanoTime(); // Paper // Folia - threaded regions - changed to nanoTime // Luminol - Fix player auto saving ignores interval
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||
private static final int FLY_STAT_RECORDING_SPEED = 25;
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 01:15:09 +0800
|
||||
Subject: [PATCH] Force disable builtin spark plugin
|
||||
|
||||
The spark passed down from paper has some memory leaking issue, so we fully removed it from the code to prevent that memory leaking issue.
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 83b9aab16124ddcc416f7b4cd95084e1c64fe5b7..7683c12d48d23dd43bce3d3b5633029c596930a5 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -672,8 +672,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
// Paper end - Configurable player collision; Handle collideRule team for player collision toggle
|
||||
this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD);
|
||||
- this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark
|
||||
- this.server.spark.enableAfterPlugins(this.server); // Paper - spark
|
||||
+ if (false) this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
|
||||
+ if (false) this.server.spark.enableAfterPlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
|
||||
io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // Paper - reset invalid state for event fire below
|
||||
io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - call commands event for regular plugins
|
||||
this.server.getCommandMap().registerServerAliases(); // Paper - relocate initial CommandMap#registerServerAliases() call
|
||||
@@ -1087,7 +1087,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
|
||||
// CraftBukkit start
|
||||
if (this.server != null) {
|
||||
- this.server.spark.disable(); // Paper - spark
|
||||
+ if (false) this.server.spark.disable(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
this.server.disablePlugins();
|
||||
this.server.waitForAsyncTasksShutdown(); // Paper - Wait for Async Tasks during shutdown
|
||||
}
|
||||
@@ -1352,7 +1352,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.statusIcon = this.loadStatusIcon().orElse(null);
|
||||
this.status = this.buildServerStatus();
|
||||
|
||||
- this.server.spark.enableBeforePlugins(); // Paper - spark
|
||||
+ if (false) this.server.spark.enableBeforePlugins(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
// Folia start - region threading
|
||||
if (true) {
|
||||
io.papermc.paper.threadedregions.RegionizedServer.getInstance().init(); // Folia - region threading - only after loading worlds
|
||||
@@ -1666,7 +1666,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
if (this.emptyTicks >= emptyTickThreshold) {
|
||||
- this.server.spark.tickStart(); // Paper - spark
|
||||
+ if (false) this.server.spark.tickStart(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
if (this.emptyTicks == emptyTickThreshold) {
|
||||
LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhenEmptySeconds());
|
||||
this.autoSave();
|
||||
@@ -1685,7 +1685,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Paper end - avoid issues with certain tasks not processing during sleep
|
||||
//this.server.spark.executeMainThreadTasks(); // Paper - spark // Folia - region threading
|
||||
this.tickConnection();
|
||||
- this.server.spark.tickEnd(((double)(System.nanoTime() - this.currentTickStart) / 1000000D)); // Paper - spark
|
||||
+ if (false) this.server.spark.tickEnd(((double)(System.nanoTime() - this.currentTickStart) / 1000000D)); // Paper - spark // Luminol - Force disable builtin spark
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1698,7 +1698,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
};
|
||||
// Folia end - region threading
|
||||
|
||||
- this.server.spark.tickStart(); // Paper - spark
|
||||
+ if (false) this.server.spark.tickStart(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
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) {
|
||||
@@ -1785,7 +1785,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
|
||||
- this.server.spark.tickEnd(((double)(endTime - startTime) / 1000000D)); // Paper - spark // Folia - region threading
|
||||
+ if (false) this.server.spark.tickEnd(((double)(endTime - startTime) / 1000000D)); // Paper - spark // Folia - region threading // Luminol - Force disable builtin spark
|
||||
// Folia - region threading
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 1ad4704523a3d90414ac514488207b1b5def9afd..1145d5839e621a02b7972c2ff1142f51db2237de 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -239,7 +239,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
// Paper end - initialize global and world-defaults configuration
|
||||
me.earthme.luminol.config.ConfigManager.loadConfigFiles(); // Luminol - load config file
|
||||
- this.server.spark.enableEarlyIfRequested(); // Paper - spark
|
||||
+ if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark
|
||||
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save
|
||||
if (this.convertOldUsers()) {
|
||||
this.services().nameToIdCache().save(false); // Paper
|
||||
@@ -249,7 +249,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); // Paper - start watchdog thread
|
||||
consoleThread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized
|
||||
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
|
||||
- this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark
|
||||
+ if (false) this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
|
||||
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
|
||||
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:10:30 +0800
|
||||
Subject: [PATCH] Prevent tamable animals check can teleport in an unloaded
|
||||
chunk
|
||||
|
||||
Based on the implementation of Canvas(https://github.com/CraftCanvasMC/Canvas/commit/af2aacb12cbccfd328dda4961167786f5d9dad53)
|
||||
|
||||
We need to check canTeleport for TamableAnimal but this logic could do the check in another tick region itself, so we need to prevent that. But it needs to push off this check to schedule to the correct tickregion, which needs costly rewriting of this logic, so we could simply allow the read when the owner's position is loaded
|
||||
|
||||
diff --git a/net/minecraft/world/entity/TamableAnimal.java b/net/minecraft/world/entity/TamableAnimal.java
|
||||
index 95ba821a895c7ea8fffcbf1df2e7b3c174463d9e..b0a01673224522552672b7c8c9aa219108e8010f 100644
|
||||
--- a/net/minecraft/world/entity/TamableAnimal.java
|
||||
+++ b/net/minecraft/world/entity/TamableAnimal.java
|
||||
@@ -318,7 +318,8 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
|
||||
return false;
|
||||
}
|
||||
|
||||
- BlockState blockStateBelow = this.level().getBlockState(pos.below());
|
||||
+ BlockState blockStateBelow = this.level().getBlockStateIfLoaded(pos.below()); // Luminol - Prevent tamable animals check can teleport in an unloaded chunk
|
||||
+ if (blockStateBelow == null) return false; // Luminol - Prevent tamable animals check can teleport in an unloaded chunk
|
||||
if (!this.canFlyToOwner() && blockStateBelow.getBlock() instanceof LeavesBlock) {
|
||||
return false;
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 21:52:07 +0800
|
||||
Subject: [PATCH] Prevent teleprotAsync calls in move events
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index c1faaf7d514c23d756aa626fa93aabd8bb503463..0c5fb17e7cce18eac68183cc3b5de6fc6451dc50 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -730,7 +730,9 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
+ this.player.blockTeleportAsync = true; // Luminol - Prevent teleprotAsync calls during move events
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
+ this.player.blockTeleportAsync = false; // Luminol - Prevent teleprotAsync calls during move events
|
||||
|
||||
// If the event is cancelled we move the player back to their old location.
|
||||
if (event.isCancelled()) {
|
||||
@@ -1740,7 +1742,9 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
Location oldTo = to.clone();
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
|
||||
+ this.player.blockTeleportAsync = true; // Luminol - Prevent teleprotAsync calls during move events
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
+ this.player.blockTeleportAsync = false; // Luminol - Prevent teleprotAsync calls during move events
|
||||
|
||||
// If the event is cancelled we move the player back to their old location.
|
||||
if (event.isCancelled()) {
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index a52d5c0ba970d666fd57e075d14350ff07401bac..72f89eaba2ca8b66fa07a6378d93917dec83c688 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4476,12 +4476,25 @@ public abstract class Entity
|
||||
teleportTarget.cause(), teleportFlags, teleportComplete
|
||||
);
|
||||
}
|
||||
+ // Luminol start - Prevent teleprotAsync calls in move events
|
||||
+ public boolean blockTeleportAsync = false;
|
||||
+ // Luminol end
|
||||
|
||||
public final boolean teleportAsync(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity,
|
||||
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, long teleportFlags,
|
||||
java.util.function.Consumer<Entity> teleportComplete) {
|
||||
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot teleport entity async");
|
||||
|
||||
+ // Luminol start - Prevent teleprotAsync calls in move events
|
||||
+ if (this.blockTeleportAsync && me.earthme.luminol.config.modules.fixes.PreventIncorrectTeleportAsyncConfig.enabled) {
|
||||
+ if (me.earthme.luminol.config.modules.fixes.PreventIncorrectTeleportAsyncConfig.throwWhenCaught) {
|
||||
+ throw new IllegalStateException("Call teleportAsync during move events!");
|
||||
+ }
|
||||
+
|
||||
+ LOGGER.error("Calling teleportAsync during move events!", new Throwable());
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
if (!ServerLevel.isInSpawnableBounds(new BlockPos(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockX(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockY(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockZ(pos)))) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
index 3fcd534cee1f605a710ffc43eff4b5106c7dd40c..9b887b40236a212de513e3ceece1abfec5372ae2 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/boat/AbstractBoat.java
|
||||
@@ -282,7 +282,9 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable {
|
||||
|
||||
if (this.lastLocation != null && !this.lastLocation.equals(to)) {
|
||||
org.bukkit.event.vehicle.VehicleMoveEvent event = new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, this.lastLocation, to);
|
||||
+ this.blockTeleportAsync = true; // Luminol - Prevent teleprotAsync calls during move events
|
||||
event.callEvent();
|
||||
+ this.blockTeleportAsync = false; // Luminol - Prevent teleprotAsync calls during move events
|
||||
}
|
||||
this.lastLocation = vehicle.getLocation();
|
||||
// CraftBukkit end
|
||||
diff --git a/net/minecraft/world/entity/vehicle/minecart/AbstractMinecart.java b/net/minecraft/world/entity/vehicle/minecart/AbstractMinecart.java
|
||||
index 5ad77636d0681d1f0341cff4482ba6ad52f3583b..0ae8b5222c5f2f608af352cbaa866c493dd065aa 100644
|
||||
--- a/net/minecraft/world/entity/vehicle/minecart/AbstractMinecart.java
|
||||
+++ b/net/minecraft/world/entity/vehicle/minecart/AbstractMinecart.java
|
||||
@@ -318,7 +318,9 @@ public abstract class AbstractMinecart extends VehicleEntity {
|
||||
new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle).callEvent();
|
||||
|
||||
if (!from.equals(to)) {
|
||||
+ this.blockTeleportAsync = true; // Luminol - Prevent teleprotAsync calls during move events
|
||||
new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to).callEvent();
|
||||
+ this.blockTeleportAsync = false; // Luminol - Prevent teleprotAsync calls during move events
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.updateFluidInteraction();
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:19:31 +0800
|
||||
Subject: [PATCH] Sync dragon part when teleportation or firstly created
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
index b31b55f00e2ce1bd6c1011fe852bd1dbb37de524..75c36cbf86e56d4993169688a13f22ccef555d92 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||
@@ -97,6 +97,7 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()), enderpearl.getId()); // Folia - region threading
|
||||
}
|
||||
+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||
entity.registerScheduler(); // Paper - optimise Folia entity scheduler
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 72f89eaba2ca8b66fa07a6378d93917dec83c688..6b7382f06a8c76b216b081e66789fe51466b1e29 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4460,6 +4460,7 @@ public abstract class Entity
|
||||
Entity copy = this.getType().create(destination, EntitySpawnReason.DIMENSION_TRAVEL);
|
||||
copy.restoreFrom(this);
|
||||
copy.transform(pos, yaw, pitch, velocity);
|
||||
+ if (copy instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Luminol - Sync dragon part when teleportation or firstly created
|
||||
// vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here
|
||||
// for example, clearing of inventory after switching dimensions
|
||||
this.postRemoveAfterChangingDimensions();
|
||||
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index ab921ab4b4cc860abd77744f2bd201013e136e51..fd85816ec78c99f45c740ebf8052ff41f4859ed6 100644
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -1011,4 +1011,12 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
return 500;
|
||||
}
|
||||
// Paper end - init expToDrop for already dying spawned dragon
|
||||
+
|
||||
+ // Luminol start - Sync dragon part when teleportation or firstly created
|
||||
+ public void syncDragonPartsAfterTeleportTransform() {
|
||||
+ for (EnderDragonPart part : this.subEntities) {
|
||||
+ this.tickPart(part, 0.0, 0.0, 0.0); // offset -> 0.0
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:32:34 +0800
|
||||
Subject: [PATCH] Teleport async if entity was moving to another region at once
|
||||
|
||||
On folia, entity usually cannot move out of the tickregion, but sometimes it actually does(like some end pearl gun that can shoot an end pearl to the block faraway than 10000 blocks even more). To fix this, we added a temporary fix which teleport these entities to the destination instead running its move logics so that we could ensure anything is under control.But one thing need to consider is that teleportAsync is actually calling halfway of the entity tick and there is still something running when teleportAsync called, which is actually modified the entity in another thread, so there is still need an improvement
|
||||
|
||||
Reference from : https://github.com/KaiijuMC/Kaiiju/blob/ver/1.20.1/patches/server/0040-Teleport-async-if-we-cannot-move-entity-off-main.patch
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 6b7382f06a8c76b216b081e66789fe51466b1e29..8c909108a0c468f353837787188c12f907369b9b 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1163,6 +1163,19 @@ public abstract class Entity
|
||||
this.moveStartZ = this.getZ();
|
||||
this.moveVector = delta;
|
||||
}
|
||||
+ //Luminol start - Fix high position moving
|
||||
+ // Filter the threads as it may be called by the chunk system worker thread
|
||||
+ if (me.earthme.luminol.config.modules.fixes.FoliaEntityMovingFixConfig.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()){
|
||||
+ var finalPosition = delta.add(this.position);
|
||||
+ // not NaN (Prevent incorrect checks under NaN minecarts)
|
||||
+ if (!Double.isNaN(finalPosition.x) && !Double.isNaN(finalPosition.y) && !Double.isNaN(finalPosition.z)) {
|
||||
+ // kill tick passively if it's moving out of region and we'll catch this exception
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level,finalPosition)) {
|
||||
+ throw new me.earthme.luminol.utils.EntityMoveOutOfRegionException(this, delta, moverType);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ //Luminol end
|
||||
try {
|
||||
// Paper end - detailed watchdog information
|
||||
if (this.noPhysics) {
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index a0eb1f608a99301e0197ab1d1a6fbbb0a0be4ce0..dc28223684091cd0d8dbf7ff01626b20e4f1b662 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -1571,6 +1571,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
public <T extends Entity> void guardEntityTick(final Consumer<T> tick, final T entity) {
|
||||
try {
|
||||
tick.accept(entity);
|
||||
+ } catch (me.earthme.luminol.utils.EntityMoveOutOfRegionException moveOutOfRegionException) { // Luminol - Teleport async if entity was moving to another region at once
|
||||
+ // Luminol start - Teleport async if entity was moving to another region at once
|
||||
+ final Entity ent = moveOutOfRegionException.getEntity();
|
||||
+ var currPosition = ent.position();
|
||||
+ var toPosition = moveOutOfRegionException.getMovement().add(currPosition);
|
||||
+
|
||||
+ if (me.earthme.luminol.config.modules.fixes.FoliaEntityMovingFixConfig.warnOnDetected) {
|
||||
+ MinecraftServer.LOGGER.warn("Entity {} with entityId {} has tried moving to another region!",ent, ent.getId());
|
||||
+ }
|
||||
+
|
||||
+ ent.getBukkitEntity().taskScheduler.schedule(entityFresh -> entityFresh.teleportAsync(
|
||||
+ (ServerLevel) entityFresh.level(),
|
||||
+ toPosition,
|
||||
+ entityFresh.getYRot(), entityFresh.getXRot(),
|
||||
+ entityFresh.getDeltaMovement(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN,
|
||||
+ Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS,
|
||||
+ null
|
||||
+ ), null, 1L);
|
||||
+ // Luminol end
|
||||
} catch (Throwable t) {
|
||||
// Paper start - Prevent block entity and entity crashes
|
||||
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", io.papermc.paper.util.MCUtil.getLevelName(entity.level()), entity.getX(), entity.getY(), entity.getZ());
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 01:28:05 +0800
|
||||
Subject: [PATCH] Temporarily fix teleport yam and pitch
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/commands/TeleportCommand.java b/net/minecraft/server/commands/TeleportCommand.java
|
||||
index 13d7965fd4f99f0848b080349df41f8b1c31a19b..37268fe5d1f21d5b08ed4a1c0e5777bcb062c8e6 100644
|
||||
--- a/net/minecraft/server/commands/TeleportCommand.java
|
||||
+++ b/net/minecraft/server/commands/TeleportCommand.java
|
||||
@@ -248,8 +248,10 @@ public class TeleportCommand {
|
||||
// Folia start - region threading
|
||||
if (true) {
|
||||
Vec3 posFinal = new Vec3(x, y, z);
|
||||
- Float yawFinal = Float.valueOf(newYRot);
|
||||
- Float pitchFinal = Float.valueOf(newXRot);
|
||||
+ //Float yawFinal = Float.valueOf(newYRot); // Luminol - fix teleport yaw issue
|
||||
+ //Float pitchFinal = Float.valueOf(newXRot); // Luminol - fix teleport yaw issue
|
||||
+ Float yawFinal = Float.valueOf(newYRot + victim.getYRot()); // Luminol - fix teleport yaw issue
|
||||
+ Float pitchFinal = Float.valueOf(newXRot + victim.getXRot()); // Luminol - fix teleport pitch issue
|
||||
victim.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> {
|
||||
nmsEntity.stopRiding();
|
||||
nmsEntity.teleportAsync(
|
||||
@@ -0,0 +1,288 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:47:24 +0800
|
||||
Subject: [PATCH] Improved Server Health Report
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/commands/CommandServerHealth.java b/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
||||
index aa860cfe9de616f185163fe74e0f4f49bd13a805..05d4f73340412f737224cb1443ecf1e33586ed38 100644
|
||||
--- a/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
||||
+++ b/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
||||
@@ -29,6 +29,14 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
+// Luminol start - Improved Server Health Report
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.lang.management.ManagementFactory;
|
||||
+import java.lang.management.MemoryMXBean;
|
||||
+import java.lang.management.MemoryUsage;
|
||||
+import java.lang.management.RuntimeMXBean;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+// Luminol end
|
||||
|
||||
public final class CommandServerHealth extends Command {
|
||||
|
||||
@@ -45,7 +53,7 @@ public final class CommandServerHealth extends Command {
|
||||
private static final TextColor HEADER = TextColor.color(79, 164, 240);
|
||||
private static final TextColor PRIMARY = TextColor.color(48, 145, 237);
|
||||
private static final TextColor SECONDARY = TextColor.color(104, 177, 240);
|
||||
- private static final TextColor INFORMATION = TextColor.color(145, 198, 243);
|
||||
+ private static final TextColor INFORMATION = TextColor.color(180, 220, 255); // Luminol start - Improved Server Health Report
|
||||
private static final TextColor LIST = TextColor.color(33, 97, 188);
|
||||
|
||||
public CommandServerHealth() {
|
||||
@@ -60,9 +68,11 @@ public final class CommandServerHealth extends Command {
|
||||
return Component.text()
|
||||
.append(Component.text(prefix, PRIMARY, TextDecoration.BOLD))
|
||||
.append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0), CommandUtil.getUtilisationColourRegion(util)))
|
||||
- .append(Component.text("% util at ", PRIMARY))
|
||||
+ .append(Component.text("% util", PRIMARY))
|
||||
+ .append(Component.text(" | ", SECONDARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt), CommandUtil.getColourForMSPT(mspt)))
|
||||
- .append(Component.text(" MSPT at ", PRIMARY))
|
||||
+ .append(Component.text(" mspt", PRIMARY))
|
||||
+ .append(Component.text(" | ", SECONDARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(tps), CommandUtil.getColourForTPS(tps)))
|
||||
.append(Component.text(" TPS" + (newline ? "\n" : ""), PRIMARY))
|
||||
.build();
|
||||
@@ -81,7 +91,7 @@ public final class CommandServerHealth extends Command {
|
||||
|
||||
private static boolean executeRegion(final CommandSender sender, final String commandLabel, final String[] args) {
|
||||
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region =
|
||||
- TickRegionScheduler.getCurrentRegion();
|
||||
+ TickRegionScheduler.getCurrentRegion();
|
||||
if (region == null) {
|
||||
sender.sendMessage(Component.text("You are not in a region currently", NamedTextColor.RED));
|
||||
return true;
|
||||
@@ -105,8 +115,7 @@ public final class CommandServerHealth extends Command {
|
||||
final double tps1m = report1m.tpsData().segmentAll().average();
|
||||
final double mspt1m = report1m.timePerTickData().segmentAll().average() / 1.0E6;
|
||||
|
||||
- final int yLoc = 80;
|
||||
- final String location = "[w:'" + world.getWorld().getName() + "'," + centerBlockX + "," + yLoc + "," + centerBlockZ + "]";
|
||||
+ final String location = world.getWorld().getName() + " (" + centerBlockX + ", " + centerBlockZ + ")";
|
||||
|
||||
final Component line = Component.text()
|
||||
.append(Component.text("Region around block ", PRIMARY))
|
||||
@@ -144,7 +153,7 @@ public final class CommandServerHealth extends Command {
|
||||
}
|
||||
|
||||
final List<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>> regions =
|
||||
- new ArrayList<>();
|
||||
+ new ArrayList<>();
|
||||
|
||||
for (final World bukkitWorld : Bukkit.getWorlds()) {
|
||||
final ServerLevel world = ((CraftWorld)bukkitWorld).getHandle();
|
||||
@@ -163,6 +172,18 @@ public final class CommandServerHealth extends Command {
|
||||
final long currTime = System.nanoTime();
|
||||
final TickData.TickReportData globalTickReport = RegionizedServer.getGlobalTickData().getTickReport15s(currTime);
|
||||
|
||||
+ final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
|
||||
+ final MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
|
||||
+ final long usedMemory = heapUsage.getUsed() / (1024 * 1024);
|
||||
+ final long maxMemory = heapUsage.getMax() / (1024 * 1024);
|
||||
+
|
||||
+ final double memPercent = (double) usedMemory / maxMemory * 100.0;
|
||||
+ final TextColor memColor = memPercent < 60 ? CommandUtil.getUtilisationColourRegion(0.0) : (memPercent < 85 ? NamedTextColor.YELLOW : NamedTextColor.RED);
|
||||
+
|
||||
+ final RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||
+ final long uptime = runtimeBean.getUptime();
|
||||
+ final String uptimeStr = formatUptime(uptime);
|
||||
+
|
||||
for (final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region : regions) {
|
||||
final TickData.TickReportData report = region.getData().getRegionSchedulingHandle().getTickReport15s(currTime);
|
||||
tpsByRegion.add(report == null ? 20.0 : report.tpsData().segmentAll().average());
|
||||
@@ -174,31 +195,27 @@ public final class CommandServerHealth extends Command {
|
||||
final double loadRate = ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkFullTask.loadRate(currTime);
|
||||
|
||||
totalUtil += globalTickReport.utilisation();
|
||||
+ final TextColor utilisationColor = CommandUtil.getUtilisationColourRegion(totalUtil / (double)maxThreadCount);
|
||||
|
||||
tpsByRegion.sort(null);
|
||||
if (!tpsByRegion.isEmpty()) {
|
||||
minTps = tpsByRegion.getDouble(0);
|
||||
maxTps = tpsByRegion.getDouble(tpsByRegion.size() - 1);
|
||||
-
|
||||
final int middle = tpsByRegion.size() >> 1;
|
||||
if ((tpsByRegion.size() & 1) == 0) {
|
||||
- // even, average the two middle points
|
||||
medianTps = (tpsByRegion.getDouble(middle - 1) + tpsByRegion.getDouble(middle)) / 2.0;
|
||||
} else {
|
||||
- // odd, can just grab middle
|
||||
medianTps = tpsByRegion.getDouble(middle);
|
||||
}
|
||||
} else {
|
||||
- // no regions = green
|
||||
minTps = medianTps = maxTps = 20.0;
|
||||
}
|
||||
|
||||
final List<ObjectObjectImmutablePair<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>, TickData.TickReportData>>
|
||||
- regionsBelowThreshold = new ArrayList<>();
|
||||
+ regionsBelowThreshold = new ArrayList<>();
|
||||
|
||||
for (int i = 0, len = regions.size(); i < len; ++i) {
|
||||
final TickData.TickReportData report = reportsByRegion.get(i);
|
||||
-
|
||||
regionsBelowThreshold.add(new ObjectObjectImmutablePair<>(regions.get(i), report));
|
||||
}
|
||||
|
||||
@@ -207,11 +224,18 @@ public final class CommandServerHealth extends Command {
|
||||
final TickData.TickReportData report2 = p2.right();
|
||||
final double util1 = report1 == null ? 0.0 : report1.utilisation();
|
||||
final double util2 = report2 == null ? 0.0 : report2.utilisation();
|
||||
-
|
||||
- // we want the largest first
|
||||
return Double.compare(util2, util1);
|
||||
});
|
||||
|
||||
+ long totalChunks = 0;
|
||||
+ long totalEntities = 0;
|
||||
+
|
||||
+ for (final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region : regions) {
|
||||
+ final TickRegions.RegionStats stats = region.getData().getRegionStats();
|
||||
+ totalChunks += stats.getChunkCount();
|
||||
+ totalEntities += stats.getEntityCount();
|
||||
+ }
|
||||
+
|
||||
final TextComponent.Builder lowestRegionsBuilder = Component.text();
|
||||
|
||||
if (sender instanceof Player) {
|
||||
@@ -219,23 +243,18 @@ public final class CommandServerHealth extends Command {
|
||||
}
|
||||
for (int i = 0, len = Math.min(lowestRegionsCount, regionsBelowThreshold.size()); i < len; ++i) {
|
||||
final ObjectObjectImmutablePair<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>, TickData.TickReportData>
|
||||
- pair = regionsBelowThreshold.get(i);
|
||||
+ pair = regionsBelowThreshold.get(i);
|
||||
|
||||
final TickData.TickReportData report = pair.right();
|
||||
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region =
|
||||
- pair.left();
|
||||
+ pair.left();
|
||||
|
||||
- if (report == null) {
|
||||
- // skip regions with no data
|
||||
- continue;
|
||||
- }
|
||||
+ if (report == null) continue;
|
||||
|
||||
final ServerLevel world = region.regioniser.world;
|
||||
final ChunkPos chunkCenter = region.getCenterChunk();
|
||||
- if (chunkCenter == null) {
|
||||
- // region does not exist anymore
|
||||
- continue;
|
||||
- }
|
||||
+ if (chunkCenter == null) continue;
|
||||
+
|
||||
final int centerBlockX = ((chunkCenter.x() << 4) | 7);
|
||||
final int centerBlockZ = ((chunkCenter.z() << 4) | 7);
|
||||
final double util = report.utilisation();
|
||||
@@ -243,18 +262,21 @@ public final class CommandServerHealth extends Command {
|
||||
final double mspt = report.timePerTickData().segmentAll().average() / 1.0E6;
|
||||
|
||||
final int yLoc = 80;
|
||||
- final String location = "[w:'" + world.getWorld().getName() + "'," + centerBlockX + "," + yLoc + "," + centerBlockZ + "]";
|
||||
+ final String location = world.getWorld().getName() + " (" + centerBlockX + ", " + centerBlockZ + ")";
|
||||
+
|
||||
final Component line = Component.text()
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
- .append(Component.text("Region around block ", PRIMARY))
|
||||
+ .append(Component.text("Region at ", PRIMARY))
|
||||
.append(Component.text(location, INFORMATION))
|
||||
.append(Component.text(":\n", PRIMARY))
|
||||
|
||||
.append(Component.text(" ", PRIMARY))
|
||||
.append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0), CommandUtil.getUtilisationColourRegion(util)))
|
||||
- .append(Component.text("% util at ", PRIMARY))
|
||||
+ .append(Component.text("% util", PRIMARY))
|
||||
+ .append(Component.text(" | ", SECONDARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt), CommandUtil.getColourForMSPT(mspt)))
|
||||
- .append(Component.text(" MSPT at ", PRIMARY))
|
||||
+ .append(Component.text(" mspt", PRIMARY))
|
||||
+ .append(Component.text(" | ", SECONDARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(tps), CommandUtil.getColourForTPS(tps)))
|
||||
.append(Component.text(" TPS\n", PRIMARY))
|
||||
|
||||
@@ -270,29 +292,53 @@ public final class CommandServerHealth extends Command {
|
||||
|
||||
sender.sendMessage(
|
||||
Component.text()
|
||||
- .append(Component.text("Server Health Report\n", HEADER, TextDecoration.BOLD))
|
||||
+ .append(Component.text("Server Health Report", HEADER, TextDecoration.BOLD))
|
||||
+ .append(Component.text(" (Uptime: ", SECONDARY))
|
||||
+ .append(Component.text(uptimeStr, utilisationColor))
|
||||
+ .append(Component.text(")\n", SECONDARY))
|
||||
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
.append(Component.text("Online Players: ", PRIMARY))
|
||||
- .append(Component.text(Bukkit.getOnlinePlayers().size() + "\n", INFORMATION))
|
||||
+ .append(Component.text(Bukkit.getOnlinePlayers().size(), INFORMATION))
|
||||
+ .append(Component.newline())
|
||||
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
.append(Component.text("Total regions: ", PRIMARY))
|
||||
- .append(Component.text(regions.size() + "\n", INFORMATION))
|
||||
+ .append(Component.text(regions.size(), INFORMATION))
|
||||
+ .append(Component.text(", ", PRIMARY))
|
||||
+ .append(Component.text("Total Chunks: ", PRIMARY))
|
||||
+ .append(Component.text(NO_DECIMAL_PLACES.get().format(totalChunks), INFORMATION))
|
||||
+ .append(Component.text(", ", PRIMARY))
|
||||
+ .append(Component.text("Total Entities: ", PRIMARY))
|
||||
+ .append(Component.text(NO_DECIMAL_PLACES.get().format(totalEntities) + "\n", INFORMATION))
|
||||
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
.append(Component.text("Utilisation: ", PRIMARY))
|
||||
- .append(Component.text(ONE_DECIMAL_PLACES.get().format(totalUtil * 100.0), CommandUtil.getUtilisationColourRegion(totalUtil / (double)maxThreadCount)))
|
||||
- .append(Component.text("% / ", PRIMARY))
|
||||
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(totalUtil * 100.0), utilisationColor))
|
||||
+ .append(Component.text("%", PRIMARY))
|
||||
+ .append(Component.text(" / ", SECONDARY))
|
||||
.append(Component.text(ONE_DECIMAL_PLACES.get().format(maxThreadCount * 100.0), INFORMATION))
|
||||
.append(Component.text("%\n", PRIMARY))
|
||||
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
.append(Component.text("Load rate: ", PRIMARY))
|
||||
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(loadRate) + ", ", INFORMATION))
|
||||
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(loadRate), INFORMATION))
|
||||
+ .append(Component.text(", ", PRIMARY))
|
||||
.append(Component.text("Gen rate: ", PRIMARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(genRate) + "\n", INFORMATION))
|
||||
|
||||
+ .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
+ .append(Component.text("Memory: ", PRIMARY))
|
||||
+ .append(Component.text(NO_DECIMAL_PLACES.get().format(usedMemory), memColor))
|
||||
+ .append(Component.text(" MB", memColor))
|
||||
+ .append(Component.text(" / ", SECONDARY))
|
||||
+ .append(Component.text(NO_DECIMAL_PLACES.get().format(maxMemory), INFORMATION))
|
||||
+ .append(Component.text(" MB", INFORMATION))
|
||||
+ .append(Component.text(" (", SECONDARY))
|
||||
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(memPercent) + "%", memColor))
|
||||
+ .append(Component.text(")", SECONDARY))
|
||||
+ .append(Component.newline())
|
||||
+
|
||||
.append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
||||
.append(Component.text("Lowest Region TPS: ", PRIMARY))
|
||||
.append(Component.text(TWO_DECIMAL_PLACES.get().format(minTps) + "\n", CommandUtil.getColourForTPS(minTps)))
|
||||
@@ -361,4 +407,21 @@ public final class CommandServerHealth extends Command {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
+
|
||||
+ // Luminol start - Improved Server Health Report
|
||||
+ private static @NotNull String formatUptime(long uptimeMillis) {
|
||||
+ long days = TimeUnit.MILLISECONDS.toDays(uptimeMillis);
|
||||
+ long hours = TimeUnit.MILLISECONDS.toHours(uptimeMillis) % 24;
|
||||
+ long minutes = TimeUnit.MILLISECONDS.toMinutes(uptimeMillis) % 60;
|
||||
+ long seconds = TimeUnit.MILLISECONDS.toSeconds(uptimeMillis) % 60;
|
||||
+
|
||||
+ StringBuilder sb = new StringBuilder();
|
||||
+ if (days > 0) sb.append(days).append("d ");
|
||||
+ if (hours > 0) sb.append(hours).append("h ");
|
||||
+ if (minutes > 0) sb.append(minutes).append("m ");
|
||||
+ sb.append(seconds).append("s");
|
||||
+
|
||||
+ return sb.toString();
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
\ No newline at end of file
|
||||
@@ -0,0 +1,522 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 18:37:50 +0800
|
||||
Subject: [PATCH] World load/unload APIs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
好吧这里这一坨需要说明的太多了而且我也不是很会翻译所以就用中文注释了)
|
||||
|
||||
这一整个实现使用了一种安全点的思路,相对于folia pr里和canvas的让每个region自己卸载, 我更偏向于将调度器拆分到每个level中然后实现类似于单个level停服的逻辑,这样会更加符合直觉而且实现要更加快速而且易于排查问题
|
||||
|
||||
由于世界卸载可能发生在玩家登录或者传送的过程中,所以我使用了引用计数器来避免这个竟态条件的发生
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionShutdownThread.java b/io/papermc/paper/threadedregions/RegionShutdownThread.java
|
||||
index f2208bcd5ccf3bd5a428e8ea3bf3ff26b3c9483b..d5c4e9b82f2ebc135b6747d19678b1a15e808ec8 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionShutdownThread.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionShutdownThread.java
|
||||
@@ -14,11 +14,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
-public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.util.TickThread {
|
||||
+public class RegionShutdownThread extends ca.spottedleaf.moonrise.common.util.TickThread { // Luminol - Level schedulers - Make public
|
||||
|
||||
- private static final Logger LOGGER = LogUtils.getClassLogger();
|
||||
+ public static final Logger LOGGER = LogUtils.getClassLogger(); // Luminol - Level schedulers - Make public
|
||||
|
||||
- ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> shuttingDown;
|
||||
+ public ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> shuttingDown; // Luminol - Level schedulers - Make public
|
||||
|
||||
public RegionShutdownThread(final String name) {
|
||||
super(name);
|
||||
@@ -52,7 +52,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
// the data required to do that is regionised, and we can only access it when we OWN the region, and we do not.
|
||||
// Thus, the only operation that the shutdown thread will perform
|
||||
|
||||
- private void saveLevelData(final ServerLevel world) {
|
||||
+ public void saveLevelData(final ServerLevel world) { // Luminol - Level hot unload apis - Make public
|
||||
try {
|
||||
world.saveLevelData(true);
|
||||
} catch (final Throwable thr) {
|
||||
@@ -60,7 +60,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
}
|
||||
}
|
||||
|
||||
- private void finishTeleportations(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region,
|
||||
+ public void finishTeleportations(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region, // Luminol - Level hot unload apis - Make public
|
||||
final ServerLevel world) {
|
||||
try {
|
||||
this.shuttingDown = region;
|
||||
@@ -94,7 +94,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
}
|
||||
}
|
||||
|
||||
- private void saveRegionChunks(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region,
|
||||
+ public void saveRegionChunks(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region, // Luminol - Level hot unload apis - Make public
|
||||
final boolean last) {
|
||||
ChunkPos center = null;
|
||||
try {
|
||||
@@ -109,7 +109,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
}
|
||||
}
|
||||
|
||||
- private void haltChunkSystem(final ServerLevel world) {
|
||||
+ public void haltChunkSystem(final ServerLevel world) { // Luminol - Level hot unload apis - Make public
|
||||
try {
|
||||
world.moonrise$getChunkTaskScheduler().chunkHolderManager.close(false, true, true, false, false);
|
||||
} catch (final Throwable thr) {
|
||||
@@ -117,7 +117,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
}
|
||||
}
|
||||
|
||||
- private void closePlayerInventories(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region) {
|
||||
+ public void closePlayerInventories(final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region) { // Luminol - Level hot unload apis - Make public
|
||||
ChunkPos center = null;
|
||||
try {
|
||||
this.shuttingDown = region;
|
||||
@@ -150,7 +150,7 @@ public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.u
|
||||
}
|
||||
|
||||
@Override
|
||||
- public final void run() {
|
||||
+ public void run() { // Luminol - Level hot unload apis - Make public
|
||||
// await scheduler termination
|
||||
LOGGER.info("Awaiting scheduler termination for 60s...");
|
||||
if (TickRegions.getScheduler().halt(true, TimeUnit.SECONDS.toNanos(60L))) {
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index aa575f3b76ef70ffb9f0410e7e5cfe7af384bfbd..ff90abb47203c03636d3175f2b3efcf43517b3b0 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -63,6 +63,12 @@ public final class RegionizedServer {
|
||||
this.worlds.add(world);
|
||||
}
|
||||
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ public void removeWorld(final ServerLevel world) {
|
||||
+ this.worlds.remove(world);
|
||||
+ }
|
||||
+ // Luminol end
|
||||
+
|
||||
public void init() {
|
||||
// call init event _before_ scheduling anything
|
||||
new RegionizedServerInitEvent().callEvent();
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index 5a72fa0d72bfdb927293abe921c57f6ae964a6ec..f8344f640f119e3865f2718d1abd0ede9bdb8aa8 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -49,7 +49,7 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
// Folia end - watchdog
|
||||
|
||||
- private final Scheduler scheduler;
|
||||
+ public final Scheduler scheduler; // Luminol - Level schedulers - Make public
|
||||
|
||||
public static enum SchedulerType {
|
||||
EDF,
|
||||
@@ -220,7 +220,15 @@ public final class TickRegionScheduler {
|
||||
*/
|
||||
public void scheduleRegion(final RegionScheduleHandle region) {
|
||||
region.scheduler = this;
|
||||
+ // this.scheduler.schedule(region); // Luminol - Level schedulers
|
||||
+ // Luminol start - Level schedulers
|
||||
+ if(region.region != null) {
|
||||
+ region.region.world.levelScheduler.schedule(region);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
this.scheduler.schedule(region);
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,13 +241,77 @@ public final class TickRegionScheduler {
|
||||
region.markNonSchedulable();
|
||||
}
|
||||
|
||||
+ // Luminol start - Level schedulers
|
||||
+ private void handleParentSchedulerDead() {
|
||||
+ for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
|
||||
+ level.levelScheduler.onParentHalted();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean haltAndWaitLevelSchedulerHalt(final boolean sync, final long maxWaitNS) {
|
||||
+ final long deadline = System.nanoTime() + maxWaitNS;
|
||||
+
|
||||
+ boolean hasUnhaltedLevelScheduler = false;
|
||||
+ for (net.minecraft.server.level.ServerLevel serverLevel : MinecraftServer.getServer().getAllLevels()) {
|
||||
+ serverLevel.levelScheduler.halt(); // ensure it's halted so that we could skip running any other new tasks
|
||||
+
|
||||
+ // block any new reading reference acquiring going into this lock
|
||||
+ serverLevel.levelUnloadStateLock.blockReadingReferencing();
|
||||
+
|
||||
+ // sync not required, directly go next
|
||||
+ if (!sync) {
|
||||
+ hasUnhaltedLevelScheduler |= !serverLevel.levelScheduler.isFullyExited();
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final boolean writeLockHeld = serverLevel.levelUnloadStateLock.acquireWrite(deadline);
|
||||
+ // we got the write lock, abort the others unloading logics
|
||||
+ if (writeLockHeld) {
|
||||
+ serverLevel.levelUnloadStateLock.acquireUnreachable();
|
||||
+
|
||||
+ // since there is no unloading tasks, so the callback would be always empty, just directly go next,
|
||||
+ // and we'll handle the final saving in global shutdown logics
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // cannot get write lock, might be marked as unreachable
|
||||
+ final boolean isUnreachable = serverLevel.levelUnloadStateLock.isUnreachable();
|
||||
+ // already fully terminated (we mark it as unreachable after all separate unload saving logics), check the scheduler state
|
||||
+ if (isUnreachable) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // try linearly block wait for halt
|
||||
+ long failures = 0L;
|
||||
+ while (!serverLevel.levelScheduler.isFullyExited()) {
|
||||
+ // check deadline
|
||||
+ if (deadline - System.nanoTime() <= 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ failures = ca.spottedleaf.concurrentutil.util.ConcurrentUtil.linearLongBackoffDeadline(failures, 100, 1000L, deadline);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return !hasUnhaltedLevelScheduler;
|
||||
+ }
|
||||
+ // Luminol end - Level schedulers
|
||||
+
|
||||
public boolean halt(final boolean sync, final long maxWaitNS) {
|
||||
- this.scheduler.halt();
|
||||
+ final boolean allLevelSchedulersExited = this.haltAndWaitLevelSchedulerHalt(sync, maxWaitNS); // Luminol - Level schedulers
|
||||
+ if (allLevelSchedulersExited) this.scheduler.halt(); // Luminol - Level schedulers
|
||||
if (!sync) {
|
||||
return this.scheduler.getAliveThreads().length == 0;
|
||||
}
|
||||
|
||||
- return this.scheduler.join(maxWaitNS == 0L ? 0L : Math.max(1L, TimeUnit.NANOSECONDS.toMillis(maxWaitNS)));
|
||||
+ // return this.scheduler.join(maxWaitNS == 0L ? 0L : Math.max(1L, TimeUnit.NANOSECONDS.toMillis(maxWaitNS))); // Luminol - Level schedulers
|
||||
+ // Luminol start - Level schedulers
|
||||
+ final boolean waitResult = allLevelSchedulersExited && this.scheduler.join(maxWaitNS == 0L ? 0L : Math.max(1L, TimeUnit.NANOSECONDS.toMillis(maxWaitNS)));
|
||||
+
|
||||
+ this.handleParentSchedulerDead();
|
||||
+
|
||||
+ return waitResult;
|
||||
+ // Luminol - end
|
||||
}
|
||||
|
||||
void dumpAliveThreadTraces(final String reason) {
|
||||
@@ -251,7 +323,15 @@ public final class TickRegionScheduler {
|
||||
}
|
||||
|
||||
public void setHasTasks(final RegionScheduleHandle region) {
|
||||
+ //this.scheduler.notifyTasks(region); // Luminol - Level schedulers
|
||||
+ // Luminol start - Level schedulers
|
||||
+ if (region.region != null) {
|
||||
+ region.region.world.levelScheduler.notifyTasks(region);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
this.scheduler.notifyTasks(region);
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
private void uncaughtException(final Thread thread, final Throwable thr) {
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 7683c12d48d23dd43bce3d3b5633029c596930a5..ab61d18845827ac835edf92651d0b510358106ff 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -236,7 +236,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
private String localIp;
|
||||
private int port = -1;
|
||||
private final LayeredRegistryAccess<RegistryLayer> registries;
|
||||
- private Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap();
|
||||
+ private volatile Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap(); // Luminol - World hot load/unload apis
|
||||
private PlayerList playerList;
|
||||
private volatile boolean running = true;
|
||||
private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart
|
||||
@@ -2034,14 +2034,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
- public void addLevel(ServerLevel level) {
|
||||
+ public synchronized void addLevel(ServerLevel level) { // Luminol - World hot load/unload apis
|
||||
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
||||
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
||||
newLevels.put(level.dimension(), level);
|
||||
this.levels = Collections.unmodifiableMap(newLevels);
|
||||
}
|
||||
|
||||
- public void removeLevel(ServerLevel level) {
|
||||
+ public synchronized void removeLevel(ServerLevel level) { // Luminol - World hot load/unload apis
|
||||
Map<ResourceKey<Level>, ServerLevel> oldLevels = this.levels;
|
||||
Map<ResourceKey<Level>, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels);
|
||||
newLevels.remove(level.dimension());
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 534f103234eb92571c664cbcfea4ce4e990d3ea8..c4d9d890db784d376b876d70f0468df6edb75168 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -221,6 +221,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
private final StructureCheck structureCheck;
|
||||
public final boolean tickTime; // Folia - region threading
|
||||
private final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
|
||||
+ // Luminol start - Level schedulers
|
||||
+ private static final java.util.concurrent.atomic.AtomicInteger UNLOADER_ID_GEN = new java.util.concurrent.atomic.AtomicInteger(0);
|
||||
+ public final me.earthme.luminol.utils.thread.LevelAwareRegionScheduler levelScheduler = new me.earthme.luminol.utils.thread.LevelAwareRegionScheduler(io.papermc.paper.threadedregions.TickRegions.getScheduler().scheduler);
|
||||
+ public final me.earthme.luminol.utils.thread.SimpleReferenceRWLock levelUnloadStateLock = new me.earthme.luminol.utils.thread.SimpleReferenceRWLock();
|
||||
+ public final me.earthme.luminol.utils.thread.LevelSubRegionShutdownThread levelUnloader = new me.earthme.luminol.utils.thread.LevelSubRegionShutdownThread("Level Unload Thread - " + UNLOADER_ID_GEN.getAndIncrement(), this);
|
||||
+ // Luminol end
|
||||
|
||||
// CraftBukkit start
|
||||
private final ResourceKey<LevelStem> typeKey;
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 264de9099b19779f20ad23c41d0967670759ae12..ab6229ee412cf2aa5affc87510230c587765080b 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1705,7 +1705,30 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
|
||||
ServerLevel origin = this.level();
|
||||
ServerPlayer.RespawnConfig respawnConfig = this.getRespawnConfig();
|
||||
- ServerLevel respawnWorld = this.server.getLevel(ServerPlayer.RespawnConfig.getDimensionOrDefault(respawnConfig));
|
||||
+ ServerLevel respawnWorldLookup = this.server.getLevel(ServerPlayer.RespawnConfig.getDimensionOrDefault(respawnConfig)); // Luminol - Level hot unload apis
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ var toLockRelease = (ServerLevel)null;
|
||||
+ if (respawnWorldLookup != null) {
|
||||
+ if (respawnWorldLookup.levelUnloadStateLock.acquireRead()) {
|
||||
+ toLockRelease = respawnWorldLookup;
|
||||
+ } else {
|
||||
+ respawnWorldLookup = null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final ServerLevel respawnWorld = respawnWorldLookup;
|
||||
+ final ServerLevel finalToLockRelease = toLockRelease;
|
||||
+
|
||||
+ var finalRespawnCompleteCallback = (java.util.function.Consumer<ServerPlayer>) player -> {
|
||||
+ if (finalToLockRelease != null) {
|
||||
+ finalToLockRelease.levelUnloadStateLock.releaseRead();
|
||||
+ }
|
||||
+
|
||||
+ if (respawnComplete != null) {
|
||||
+ respawnComplete.accept(player);
|
||||
+ }
|
||||
+ };
|
||||
+ // Luminol end
|
||||
|
||||
// modified based off PlayerList#respawn
|
||||
|
||||
@@ -1756,8 +1779,8 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
// now the respawn logic is complete
|
||||
|
||||
// last, call the function callback
|
||||
- if (respawnComplete != null) {
|
||||
- respawnComplete.accept(ServerPlayer.this);
|
||||
+ if (finalRespawnCompleteCallback != null) { // Luminol - Level hot unload apis
|
||||
+ finalRespawnCompleteCallback.accept(ServerPlayer.this); // Luminol - Level hot unload apis
|
||||
}
|
||||
}
|
||||
);
|
||||
diff --git a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
index 97f4c546663fb19558246366a3d8d77f2b9327ef..e5304e9d1ea57c01a1147621a42a9b584878f765 100644
|
||||
--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
@@ -210,8 +210,23 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
|
||||
|
||||
this.switchToMain = serverPlayer;
|
||||
// now the connection responsibility is transferred to the region
|
||||
- final net.minecraft.server.level.ServerLevel world = this.prepareSpawnTask.getSpawnWorld();
|
||||
+ net.minecraft.server.level.ServerLevel worldLookup = this.prepareSpawnTask.getSpawnWorld(); // Luminol - Level hot unload apis - world -> worldLookup, make mutable
|
||||
final net.minecraft.world.level.ChunkPos chunkPos = net.minecraft.world.level.ChunkPos.containing(net.minecraft.core.BlockPos.containing(this.prepareSpawnTask.getSpawnPosition()));
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ if (!worldLookup.levelUnloadStateLock.acquireRead()) {
|
||||
+ LOGGER.warn("Failed to acquire read reference for level {} for player placement, sending back to overworld!", worldLookup.dimension());
|
||||
+
|
||||
+ worldLookup = net.minecraft.server.MinecraftServer.getServer().overworld();
|
||||
+ if (!worldLookup.levelUnloadStateLock.acquireRead()) {
|
||||
+ throw new java.lang.IllegalStateException("Reference read for overworld should be always acquirable!");
|
||||
+ }
|
||||
+
|
||||
+ serverPlayer.setServerLevel(worldLookup);
|
||||
+ }
|
||||
+ var world = worldLookup;
|
||||
+ // note: the following logics would always be successfully executed, otherwise the server go crashed
|
||||
+ // so do not care the exception handling of the callbacks following
|
||||
+ // Luminol end
|
||||
world.moonrise$getChunkTaskScheduler().scheduleTickingState(
|
||||
chunkPos.x(), chunkPos.z(), net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING, true,
|
||||
ca.spottedleaf.concurrentutil.util.Priority.HIGHER,
|
||||
@@ -223,9 +238,15 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
|
||||
);
|
||||
io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(
|
||||
world, chunkPos.x(), chunkPos.z(), () -> {
|
||||
+ try { // Luminol - Level hot unload apis
|
||||
net.minecraft.server.network.ServerConfigurationPacketListenerImpl.this.prepareSpawnTask.spawnPlayer(
|
||||
this.connection, commonListenerCookie, serverPlayer
|
||||
);
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ } finally {
|
||||
+ world.levelUnloadStateLock.releaseRead();
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
);
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/config/PrepareSpawnTask.java b/net/minecraft/server/network/config/PrepareSpawnTask.java
|
||||
index 48f51b0f94df3e59c9410129489c63a4287bc0bc..2682f8702785b1e501748a308c5e394b8b664428 100644
|
||||
--- a/net/minecraft/server/network/config/PrepareSpawnTask.java
|
||||
+++ b/net/minecraft/server/network/config/PrepareSpawnTask.java
|
||||
@@ -104,6 +104,16 @@ public class PrepareSpawnTask implements ConfigurationTask {
|
||||
spawnLevel = spawnDataLevel;
|
||||
}
|
||||
}
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ if (!spawnLevel.levelUnloadStateLock.acquireRead()) {
|
||||
+ spawnLevel = spawnDataLevel;
|
||||
+
|
||||
+ // the apis don't allow devs to unload overworld, so just simply do a check withoud fail-processing logics on it
|
||||
+ if (!spawnLevel.levelUnloadStateLock.acquireRead()) {
|
||||
+ throw new java.lang.IllegalStateException("Default level should be acquirable!");
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
// Folia start - region threading
|
||||
CompletableFuture<Vec3> spawnPosition = new java.util.concurrent.CompletableFuture<>();
|
||||
if (loadedPosition.position().isPresent()) {
|
||||
@@ -123,6 +133,10 @@ public class PrepareSpawnTask implements ConfigurationTask {
|
||||
}
|
||||
// Folia end - region threading
|
||||
// Paper end - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ final ServerLevel finalSpawnLevel = spawnLevel;
|
||||
+ spawnPosition.whenComplete((_, _) -> finalSpawnLevel.levelUnloadStateLock.releaseRead());
|
||||
+ // Luminol end
|
||||
Vec2 spawnAngle = loadedPosition.rotation().orElse(new Vec2(respawnData.yaw(), respawnData.pitch()));
|
||||
this.state = new PrepareSpawnTask.Preparing(spawnLevel, spawnPosition, spawnAngle);
|
||||
}
|
||||
@@ -272,9 +286,20 @@ public class PrepareSpawnTask implements ConfigurationTask {
|
||||
this.spawnPosition = CompletableFuture.completedFuture(spawnPosition);
|
||||
this.spawnAngle = new Vec2(location.getYaw(), location.getPitch());
|
||||
}
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ if (!this.spawnLevel.levelUnloadStateLock.acquireRead()) {
|
||||
+ LOGGER.warn("Could not fetch read reference lock for level {}! Falling back to overworld!", this.spawnLevel);
|
||||
+
|
||||
+ this.spawnLevel = net.minecraft.server.MinecraftServer.getServer().overworld();
|
||||
+ if (!this.spawnLevel.levelUnloadStateLock.acquireRead()) {
|
||||
+ throw new java.lang.IllegalStateException();
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
// Paper end - PlayerSpawnLocationEvent
|
||||
ChunkPos spawnChunk = ChunkPos.containing(BlockPos.containing(spawnPosition));
|
||||
this.chunkLoadFuture = ((ca.spottedleaf.moonrise.patches.chunk_system.MoonriseChunkLoadCounter)this.chunkLoadCounter).trackLoadWithRadius(this.spawnLevel, spawnChunk, 3, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, ca.spottedleaf.concurrentutil.util.Priority.HIGH, () -> { Preparing.this.spawnLevel.getChunkSource().addTicketWithRadius(TicketType.PLAYER_SPAWN, spawnChunk, 3); }); // Paper - rewrite chunk system
|
||||
+ this.chunkLoadFuture.whenComplete((_,_) -> this.spawnLevel.levelUnloadStateLock.releaseRead()); // Luminol - Level hot unload apis
|
||||
PrepareSpawnTask.this.loadListener.start(LevelLoadListener.Stage.LOAD_PLAYER_CHUNKS, this.chunkLoadCounter.totalChunks());
|
||||
PrepareSpawnTask.this.loadListener.updateFocus(this.spawnLevel.dimension(), spawnChunk);
|
||||
}
|
||||
@@ -291,7 +316,7 @@ public class PrepareSpawnTask implements ConfigurationTask {
|
||||
}
|
||||
|
||||
private final class Ready implements PrepareSpawnTask.State {
|
||||
- private final ServerLevel spawnLevel;
|
||||
+ private ServerLevel spawnLevel; // Luminol - Level hot unloaad apis - Make public
|
||||
private final Vec3 spawnPosition;
|
||||
private final Vec2 spawnAngle;
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 8c909108a0c468f353837787188c12f907369b9b..1dd0ce3f8af52f5ba0da1d6617489a0de2c971b2 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -392,6 +392,9 @@ public abstract class Entity
|
||||
public void inactiveTick() {
|
||||
}
|
||||
// Paper end - EAR 2
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ public me.earthme.luminol.utils.TeleportRecord lastTeleportRecord;
|
||||
+ // Luminol end
|
||||
// CraftBukkit end
|
||||
|
||||
// Paper start
|
||||
@@ -4538,6 +4541,17 @@ public abstract class Entity
|
||||
}
|
||||
}
|
||||
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ if (!destination.levelUnloadStateLock.acquireRead()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ final java.util.function.Consumer<Entity> finalTeleportComplete = entity -> {
|
||||
+ destination.levelUnloadStateLock.releaseRead();
|
||||
+
|
||||
+ if (teleportComplete != null) teleportComplete.accept(entity);
|
||||
+ };
|
||||
+ // Luminol end
|
||||
+
|
||||
// TODO any events that can modify go HERE
|
||||
|
||||
// check for same region
|
||||
@@ -4556,6 +4570,14 @@ public abstract class Entity
|
||||
}
|
||||
|
||||
for (EntityTreeNode entity : passengerTree.getFullTree()) {
|
||||
+ // Luminol start - Level hot unload apis
|
||||
+ entity.root.lastTeleportRecord = me.earthme.luminol.utils.TeleportRecord.create(
|
||||
+ (ServerLevel) entity.root.level,
|
||||
+ entity.root.position,
|
||||
+ entity.root.yRot,
|
||||
+ entity.root.xRot
|
||||
+ );
|
||||
+ // Luminol end
|
||||
entity.root.teleportSyncSameRegion(pos, yaw, pitch, velocity);
|
||||
}
|
||||
|
||||
@@ -4571,8 +4593,8 @@ public abstract class Entity
|
||||
// performs add/remove from world logic which will also perform add/remove tracker logic
|
||||
}
|
||||
|
||||
- if (teleportComplete != null) {
|
||||
- teleportComplete.accept(this);
|
||||
+ if (finalTeleportComplete != null) { // Luminol - Level hot unload apis
|
||||
+ finalTeleportComplete.accept(this); // Luminol - Level hot unload apis
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -4589,7 +4611,7 @@ public abstract class Entity
|
||||
node.root = node.root.transformForAsyncTeleport(destination, pos, yaw, pitch, velocity);
|
||||
}
|
||||
|
||||
- passengerTree.root.placeInAsync(originWorld, destination, teleportFlags, passengerTree, teleportComplete);
|
||||
+ passengerTree.root.placeInAsync(originWorld, destination, teleportFlags, passengerTree, finalTeleportComplete); // Luminol - Level hot unload apis
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -4864,6 +4886,13 @@ public abstract class Entity
|
||||
ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(initialPosition),
|
||||
ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(initialPosition)
|
||||
);
|
||||
+ // Luminol start - Level hot load/unload apis
|
||||
+ // let's acquire read reference first
|
||||
+ if (!destination.levelUnloadStateLock.acquireRead()) {
|
||||
+ // failed, destination is under unloading process
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
|
||||
// first, remove entity/passengers from world
|
||||
EntityTreeNode passengerTree = this.detachPassengers();
|
||||
@@ -4921,6 +4950,10 @@ public abstract class Entity
|
||||
if (info.postTeleportTransition() != null) {
|
||||
info.postTeleportTransition().onTransition(teleported);
|
||||
}
|
||||
+ // Luminol start - Level hot load/unload apis
|
||||
+ // all done, release the read reference
|
||||
+ destination.levelUnloadStateLock.releaseRead();
|
||||
+ // Luminol end
|
||||
|
||||
if (teleportComplete != null) {
|
||||
teleportComplete.accept(teleported);
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 01:32:38 +0800
|
||||
Subject: [PATCH] Kaiiju: Do not pathfind outside region
|
||||
|
||||
Co-authored by: Sofiane H. Djerbi <46628754+kugge@users.noreply.github.com>
|
||||
As part of: Kaiiju (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/patches/server/0028-Don-t-pathfind-outside-region.patch)
|
||||
Licensed under: GPL-3.0 (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
index b40da004b5281a041ee896ae176bfb9c4660f353..ffb8a725c41d49a0f0e023ab37bb77062d67eccc 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
@@ -117,7 +117,9 @@ public class MoveToTargetSink extends Behavior<Mob> {
|
||||
|
||||
private boolean tryComputePath(final Mob body, final WalkTarget walkTarget, final long timestamp) {
|
||||
BlockPos targetPos = walkTarget.getTarget().currentBlockPosition();
|
||||
+ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(body.level(), targetPos)) // Kaiiju - Don't pathfind outside region
|
||||
this.path = body.getNavigation().createPath(targetPos, 0);
|
||||
+ else this.path = null; // Kaiiju - Don't pathfind outside region
|
||||
this.speedModifier = walkTarget.getSpeedModifier();
|
||||
Brain<?> brain = body.getBrain();
|
||||
if (this.reachedTarget(body, walkTarget)) {
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 01:41:14 +0800
|
||||
Subject: [PATCH] Kaiiju: Entity tick and removal limiter
|
||||
|
||||
Co-authored by: Xymb <xymb@endcrystal.me>
|
||||
As part of: Kaiiju (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/patches/server/0021-Entity-ticking-throttling-removal-to-prevent-lag.patch)
|
||||
Licensed under: GPL-3.0 (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/LICENSE)
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index cb15cfbc684ae9e9d9634886f707c2df10063139..f32d118e1e925b2155cef3fcdcb1e194c541e242 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -354,6 +354,7 @@ public final class RegionizedWorldData {
|
||||
private final IteratorSafeOrderedReferenceSet<Mob> navigatingMobs = new IteratorSafeOrderedReferenceSet<>();
|
||||
public final ReferenceList<Entity> trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
|
||||
public final ReferenceList<Entity> trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
|
||||
+ public final dev.kaiijumc.kaiiju.KaiijuEntityThrottler entityThrottler = new dev.kaiijumc.kaiiju.KaiijuEntityThrottler(); // Kaiiju
|
||||
|
||||
// block ticking
|
||||
private final ObjectLinkedOpenHashSet<BlockEventData> blockEvents = new ObjectLinkedOpenHashSet<>();
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c4d9d890db784d376b876d70f0468df6edb75168..0641b98ef3298eb682ceae83f60b730f3bf90103 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -917,6 +917,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); try { // Folia - profiler
|
||||
+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterStart(); // Kaiiju
|
||||
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
|
||||
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); } // Folia - profiler
|
||||
foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); try { // Folia - profiler
|
||||
@@ -938,6 +939,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
entity.stopRiding();
|
||||
}
|
||||
+ // Kaiiju start
|
||||
+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) {
|
||||
+ dev.kaiijumc.kaiiju.KaiijuEntityThrottler.EntityThrottlerReturn throttle = regionizedWorldData.entityThrottler.tickLimiterShouldSkip(entity);
|
||||
+ if (throttle.remove && !entity.hasCustomName()) entity.remove(Entity.RemovalReason.DISCARDED);
|
||||
+ if (throttle.skip) return;
|
||||
+ }
|
||||
+ // Kaiiju end
|
||||
|
||||
profiler.push("tick");
|
||||
this.guardEntityTick(this::tickNonPassenger, entity);
|
||||
@@ -947,6 +955,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
}
|
||||
);
|
||||
+ if (dev.kaiijumc.kaiiju.KaiijuEntityLimits.enabled) regionizedWorldData.entityThrottler.tickLimiterFinish(regionizedWorldData); // Kaiiju
|
||||
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); } // Folia - profiler
|
||||
if (this.paperConfig().unsupportedSettings.ticking.blockEntities) { // Paper - option to disable ticking
|
||||
profiler.popPush("blockEntities");
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:21:31 +0800
|
||||
Subject: [PATCH] Kaiiju: Vanilla end portal teleportation
|
||||
|
||||
Co-authored by: Sofiane H. Djerbi <46628754+kugge@users.noreply.github.com>
|
||||
As part of: Kaiiju (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/patches/server/0024-Vanilla-end-portal-teleportation.patch)
|
||||
Licensed under: GPL-3.0 (https://github.com/KaiijuMC/Kaiiju/blob/c2b7aec8f7b418a39a2ec408e6411e6f752379da/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 1dd0ce3f8af52f5ba0da1d6617489a0de2c971b2..cf70a8e2fe2fe70bcdf71f8112479031d80d8b75 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4676,14 +4676,18 @@ public abstract class Entity
|
||||
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());
|
||||
+ else finalPos = Vec3.atBottomCenterOf(targetPos);
|
||||
+ // Kaiiju end
|
||||
// the portal obsidian is placed at targetPos.y - 2, so if we want to place the entity
|
||||
// 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, 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))*/Set.of(), // Kaiiju - Vanilla end teleportation
|
||||
TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET),
|
||||
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL
|
||||
)
|
||||
@@ -4698,11 +4702,15 @@ public abstract class Entity
|
||||
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
|
||||
@@ -4881,6 +4889,10 @@ public abstract class Entity
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // Kaiiju start - sync end platform spawning & entity teleportation
|
||||
+ 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); if (teleportComplete != null) {teleportComplete.accept(e);}} : teleportComplete;
|
||||
+ // Kaiiju end
|
||||
Vec3 initialPosition = this.position();
|
||||
ChunkPos initialPositionChunk = new ChunkPos(
|
||||
ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(initialPosition),
|
||||
@@ -4955,9 +4967,14 @@ public abstract class Entity
|
||||
destination.levelUnloadStateLock.releaseRead();
|
||||
// Luminol end
|
||||
|
||||
- if (teleportComplete != null) {
|
||||
+ // Kaiiju start - vanilla end teleportation
|
||||
+ /*if (teleportComplete != null) {
|
||||
teleportComplete.accept(teleported);
|
||||
+ }*/
|
||||
+ if (tpComplete != null){
|
||||
+ tpComplete.accept(teleported);
|
||||
}
|
||||
+ // Kaiiju end
|
||||
}
|
||||
);
|
||||
});
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 19:58:46 +0800
|
||||
Subject: [PATCH] Async protocol switching optimization
|
||||
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index 40f54536422fa38bd84017fc634808016b4de58b..ecaa296f576c5c90fda89e0406d6552628ef5de3 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -1067,4 +1067,127 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
}
|
||||
}
|
||||
// Paper end - Optimize network
|
||||
+ // Luminol start - async protocol switcher
|
||||
+ public <T extends PacketListener> void setupInboundProtocolAsync(
|
||||
+ ProtocolInfo<T> protocol,
|
||||
+ T packetListener,
|
||||
+ @Nullable Runnable callback,
|
||||
+ boolean resumeAutoReading
|
||||
+ ) {
|
||||
+ this.validateListener(protocol, packetListener);
|
||||
+ if (protocol.flow() != this.getReceiving()) {
|
||||
+ throw new IllegalStateException("Invalid inbound protocol: " + protocol.id());
|
||||
+ } else {
|
||||
+ this.packetListener = packetListener;
|
||||
+ this.disconnectListener = null;
|
||||
+
|
||||
+ UnconfiguredPipelineHandler.InboundConfigurationTask configMessage = UnconfiguredPipelineHandler.setupInboundProtocol(protocol);
|
||||
+ BundlerInfo bundlerInfo = protocol.bundlerInfo();
|
||||
+ if (bundlerInfo != null) {
|
||||
+ PacketBundlePacker newBundler = new PacketBundlePacker(bundlerInfo);
|
||||
+ configMessage = configMessage.andThen(context -> context.pipeline().addAfter("decoder", "bundler", newBundler));
|
||||
+ }
|
||||
+
|
||||
+ // Here we could execute it in event loop async to prevent waiting io task on main
|
||||
+ // stop reading new packets to prevent some packets came into pipeline too early
|
||||
+ this.channel.config().setAutoRead(false);
|
||||
+
|
||||
+ // do our configuration task
|
||||
+ final UnconfiguredPipelineHandler.InboundConfigurationTask finalInboundConfigurationTask = configMessage;
|
||||
+ Runnable toExecute = () -> this.channel.writeAndFlush(finalInboundConfigurationTask).addListener(future -> {
|
||||
+ try {
|
||||
+ if (future.isSuccess()) {
|
||||
+ if (callback != null) callback.run(); // retire callback if there have one
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final Throwable ex = future.cause();
|
||||
+
|
||||
+ // here we process our exceptions like that blocking one
|
||||
+ if (ex instanceof ClosedChannelException) {
|
||||
+ LOGGER.info("Connection closed during protocol change");
|
||||
+ } else {
|
||||
+ this.channel.pipeline().fireExceptionCaught(ex);
|
||||
+ }
|
||||
+ }finally {
|
||||
+ // reset auto back and resume reading if needed
|
||||
+ if (resumeAutoReading) {
|
||||
+ this.channel.config().setAutoRead(true);
|
||||
+ this.channel.read();
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ // we need to do this inside the event loop
|
||||
+ if (!this.channel.eventLoop().inEventLoop()) {
|
||||
+ this.channel.eventLoop().execute(toExecute);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ toExecute.run();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void setupOutboundProtocolAsync(
|
||||
+ ProtocolInfo<?> protocol,
|
||||
+ @Nullable Runnable callback,
|
||||
+ boolean resumeAutoReading
|
||||
+ ) {
|
||||
+ if (protocol.flow() != this.getSending()) {
|
||||
+ throw new IllegalStateException("Invalid outbound protocol: " + protocol.id());
|
||||
+ } else {
|
||||
+ UnconfiguredPipelineHandler.OutboundConfigurationTask configMessage = UnconfiguredPipelineHandler.setupOutboundProtocol(protocol);
|
||||
+ BundlerInfo bundlerInfo = protocol.bundlerInfo();
|
||||
+ if (bundlerInfo != null) {
|
||||
+ PacketBundleUnpacker newUnbundler = new PacketBundleUnpacker(bundlerInfo);
|
||||
+ configMessage = configMessage.andThen(
|
||||
+ context -> context.pipeline().addAfter("encoder", "unbundler", newUnbundler)
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ boolean isLoginProtocol = protocol.id() == ConnectionProtocol.LOGIN;
|
||||
+
|
||||
+ // Here we could execute it in event loop async to prevent waiting io task on main
|
||||
+ // stop reading new packets to prevent some packets came into pipeline too early
|
||||
+ this.channel.config().setAutoRead(false);
|
||||
+
|
||||
+ // do our configuration task
|
||||
+ final UnconfiguredPipelineHandler.OutboundConfigurationTask finalOutboundConfigurationTask = configMessage;
|
||||
+ final Runnable writeTask = () -> this.channel.writeAndFlush(
|
||||
+ finalOutboundConfigurationTask.andThen(context -> this.sendLoginDisconnect = isLoginProtocol)
|
||||
+ ).addListener(future -> {
|
||||
+ try {
|
||||
+ if (future.isSuccess()) {
|
||||
+ if (callback != null) callback.run(); // retire callback if there have one
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final Throwable ex = future.cause();
|
||||
+
|
||||
+ // here we process our exceptions like that blocking one
|
||||
+ if (ex instanceof ClosedChannelException) {
|
||||
+ LOGGER.info("Connection closed during protocol change");
|
||||
+ } else {
|
||||
+ this.channel.pipeline().fireExceptionCaught(ex);
|
||||
+ }
|
||||
+ }finally {
|
||||
+ // reset auto back and resume reading if needed
|
||||
+ if (resumeAutoReading) {
|
||||
+ this.channel.config().setAutoRead(true);
|
||||
+ this.channel.read(); // read once
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ // we need to do this inside the event loop
|
||||
+ if (!this.channel.eventLoop().inEventLoop()) {
|
||||
+ this.channel.eventLoop().execute(writeTask);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ writeTask.run();
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
+
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
index e5304e9d1ea57c01a1147621a42a9b584878f765..af337f77545df94760b12a2b2f5eaf43d18e3774 100644
|
||||
--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java
|
||||
@@ -188,8 +188,9 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
|
||||
public void handleConfigurationFinished(final ServerboundFinishConfigurationPacket packet) {
|
||||
PacketUtils.ensureRunningOnSameThread(packet, this, this.server.packetProcessor());
|
||||
this.finishCurrentTask(JoinWorldTask.TYPE);
|
||||
- this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())));
|
||||
+ // this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); // Luminol - Async protocol switch - move down
|
||||
|
||||
+ Runnable afterSwitch = () -> { // Luminol - Async protocol switch
|
||||
try {
|
||||
PlayerList playerList = this.server.getPlayerList();
|
||||
if (playerList.getPlayer(this.gameProfile.id()) != null) {
|
||||
@@ -256,6 +257,18 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis
|
||||
LOGGER.error("Couldn't place player in world", e);
|
||||
this.disconnect(DISCONNECT_REASON_INVALID_DATA);
|
||||
}
|
||||
+ // Luminol start - Async protocol switch
|
||||
+ };
|
||||
+ if (!me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) {
|
||||
+ this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())));
|
||||
+ afterSwitch.run(); // directly run callback as we won't process any packet this time
|
||||
+ } else {
|
||||
+ this.connection.setupOutboundProtocolAsync(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), () -> {
|
||||
+ // push back
|
||||
+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(afterSwitch);
|
||||
+ }, false); // we will start auto read once we set up inbound handler at placeNewPlayer in PlayerList
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0c5fb17e7cce18eac68183cc3b5de6fc6451dc50..1ea8e03a4dc39486505d21bff1d15cb2339cafc2 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2901,7 +2901,13 @@ public class ServerGamePacketListenerImpl
|
||||
} // Folia end - rewrite login process - move connection ownership to global region
|
||||
this.waitingForSwitchToConfig = true; // Folia - rewrite login process - fix bad ordering of this field write - moved down
|
||||
this.send(ClientboundStartConfigurationPacket.INSTANCE);
|
||||
+ if (!me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) { // Luminol - Async protocol switch
|
||||
this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND);
|
||||
+ // Luminol start - Async protcol switch
|
||||
+ } else {
|
||||
+ this.connection.setupOutboundProtocolAsync(ConfigurationProtocols.CLIENTBOUND, null, true);
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3786,12 +3792,26 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
final ServerConfigurationPacketListenerImpl listener = new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation())); // Paper
|
||||
+ if (!me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) { // Luminol - Async protocol switch
|
||||
this.connection
|
||||
.setupInboundProtocol(
|
||||
ConfigurationProtocols.SERVERBOUND,
|
||||
listener // Paper
|
||||
);
|
||||
new io.papermc.paper.event.connection.configuration.PlayerConnectionReconfigureEvent(listener.paperConnection).callEvent(); // Paper
|
||||
+ } // Luminol - Async protocol switch - add "{"
|
||||
+ // Luminol start - Async protocol switch - move up
|
||||
+ else
|
||||
+ this.connection.setupInboundProtocolAsync(
|
||||
+ ConfigurationProtocols.SERVERBOUND,
|
||||
+ listener,
|
||||
+ () -> {
|
||||
+ new io.papermc.paper.event.connection.configuration.PlayerConnectionReconfigureEvent(listener.paperConnection).callEvent(); // Paper
|
||||
+ },
|
||||
+ true
|
||||
+ );
|
||||
+ // Luminol end
|
||||
+ // new io.papermc.paper.event.connection.configuration.PlayerConnectionReconfigureEvent(listener.paperConnection).callEvent(); // Paper // Luminol - Async protocol switch - move up
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index f2329d1a9d9d4bf4c9d771e25e54f2f9ef65a76c..deee051c103f9797f4612e06c12f293ec54724ac 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -435,12 +435,30 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
public void handleLoginAcknowledgement(final ServerboundLoginAcknowledgedPacket packet) {
|
||||
net.minecraft.network.protocol.PacketUtils.ensureRunningOnSameThread(packet, this, this.server.packetProcessor()); // CraftBukkit
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet");
|
||||
- this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND);
|
||||
+ /*this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); // Luminol - Async protocol switch - Rewrite
|
||||
CommonListenerCookie cookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile), this.transferred);
|
||||
ServerConfigurationPacketListenerImpl configPacketListener = new ServerConfigurationPacketListenerImpl(this.server, this.connection, cookie);
|
||||
this.connection.setupInboundProtocol(ConfigurationProtocols.SERVERBOUND, configPacketListener);
|
||||
configPacketListener.startConfiguration();
|
||||
- this.state = ServerLoginPacketListenerImpl.State.ACCEPTED;
|
||||
+ this.state = ServerLoginPacketListenerImpl.State.ACCEPTED;*/ // Luminol - Async protocol switch - Rewrite
|
||||
+
|
||||
+ // Luminol start - Async protocol switch
|
||||
+ CommonListenerCookie cookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile), this.transferred);
|
||||
+ ServerConfigurationPacketListenerImpl configPacketListener = new ServerConfigurationPacketListenerImpl(this.server, this.connection, cookie);
|
||||
+
|
||||
+ Runnable afterSwitch = () -> io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(configPacketListener::startConfiguration); // push back to main thread
|
||||
+
|
||||
+ if (!me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) {
|
||||
+ this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND);
|
||||
+ this.connection.setupInboundProtocol(ConfigurationProtocols.SERVERBOUND, configPacketListener);
|
||||
+ afterSwitch.run();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.connection.setupInboundProtocolAsync(ConfigurationProtocols.SERVERBOUND, configPacketListener, () -> {
|
||||
+ this.connection.setupOutboundProtocolAsync(ConfigurationProtocols.CLIENTBOUND, afterSwitch, true); // start auto read when everything is ready
|
||||
+ }, false); // we will resume auto reading once the outbound protocol is also setup
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index e7579a9873362317dd82b63306cf650af9472574..53449af103c1774f68cb0c296d47e7032e4e3843 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -237,9 +237,11 @@ public abstract class PlayerList {
|
||||
// only after setting the connection listener to game type, add the connection to this regions list
|
||||
level.getCurrentWorldData().connections.add(connection);
|
||||
// Folia end - rewrite login process
|
||||
+ if (!me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) { // Luminol - Async protocol switch // we will run async switch once these main thread logics became done
|
||||
connection.setupInboundProtocol(
|
||||
GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()), playerConnection), playerConnection
|
||||
);
|
||||
+ } // Luminol - Async protocol switch
|
||||
playerConnection.suspendFlushing();
|
||||
GameRules gameRules = level.getGameRules();
|
||||
boolean immediateRespawn = gameRules.get(GameRules.IMMEDIATE_RESPAWN);
|
||||
@@ -403,6 +405,17 @@ public abstract class PlayerList {
|
||||
);
|
||||
}
|
||||
// Paper end - Send empty chunk
|
||||
+ // Luminol start - Async protocol switch
|
||||
+ if (me.earthme.luminol.config.modules.optimizations.AsyncProtocolChangeConfig.enabled) {
|
||||
+ // auto read will be enabled once the async switch is done
|
||||
+ connection.setupInboundProtocolAsync(
|
||||
+ GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()), playerConnection),
|
||||
+ playerConnection,
|
||||
+ null, // we don't need to do anything more
|
||||
+ true // start auto read which we have disabled in configuration handler
|
||||
+ );
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
public void updateEntireScoreboard(final ServerScoreboard scoreboard, final ServerPlayer player) {
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:08:52 +0800
|
||||
Subject: [PATCH] Add config for server mod name
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index ab61d18845827ac835edf92651d0b510358106ff..d4e31bb829451a687bf567fd0357f46fd7d46902 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2072,7 +2072,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
public String getServerModName() {
|
||||
- return io.papermc.paper.ServerBuildInfo.buildInfo().brandName(); // Paper
|
||||
+ return me.earthme.luminol.config.modules.misc.ServerModNameConfig.fakeVanilla ? "vanilla" : me.earthme.luminol.config.modules.misc.ServerModNameConfig.serverModName; // Paper // Luminol - Add config for server mod name
|
||||
}
|
||||
|
||||
public ServerClockManager clockManager() {
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:09:33 +0800
|
||||
Subject: [PATCH] Add config for offline mode warning
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 1145d5839e621a02b7972c2ff1142f51db2237de..81934fb56744dbbb3fdd100e8ec83cb634034d04 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -304,7 +304,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord";
|
||||
String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/";
|
||||
// Paper end - Add Velocity IP Forwarding Support
|
||||
- if (!this.usesAuthentication()) {
|
||||
+ if (!this.usesAuthentication() && !me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableOfflineModeWarning) { //Luminol - Add config for offline mod warning
|
||||
LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
|
||||
LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
|
||||
// Spigot start
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 17 Apr 2026 22:47:34 +0800
|
||||
Subject: [PATCH] Add config for cpu affinity
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index f8344f640f119e3865f2718d1abd0ede9bdb8aa8..58e557923dfe6cee39ec45e7f5aa43a5ded9f107 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -66,7 +66,7 @@ public final class TickRegionScheduler {
|
||||
|
||||
@Override
|
||||
public Thread newThread(final Runnable run) {
|
||||
- final Thread ret = new TickThreadRunner(this.threadGroup, run, "Folia Region Scheduler Thread #" + this.idGenerator.getAndIncrement());
|
||||
+ final Thread ret = new TickThreadRunner(this.threadGroup, me.earthme.luminol.config.modules.optimizations.CpuAffinityConfig.wrapForTickRegion(run), "Folia Region Scheduler Thread #" + this.idGenerator.getAndIncrement()); // Luminol - cpu affinity
|
||||
ret.setUncaughtExceptionHandler(TickRegionScheduler.this::uncaughtException);
|
||||
return ret;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 01:47:51 +0800
|
||||
Subject: [PATCH] Add config for unsafe teleportation
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
index 480b6b2405706fd4d7158d0e160adafd84099887..137389f7ee97fc3a15c8f5f87c058065af91264e 100644
|
||||
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
|
||||
@@ -70,7 +70,7 @@ public class FallingBlockEntity extends Entity {
|
||||
public int fallDamageMax = 40;
|
||||
public float fallDamagePerDistance = 0.0F;
|
||||
public @Nullable CompoundTag blockData;
|
||||
- public boolean forceTickAfterTeleportToDuplicate;
|
||||
+ public boolean forceTickAfterTeleportToDuplicate = me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled; // Luminol - Unsafe teleportation
|
||||
protected static final EntityDataAccessor<BlockPos> DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
|
||||
public boolean autoExpire = true; // Paper - Expand FallingBlock API
|
||||
|
||||
@@ -384,7 +384,7 @@ public class FallingBlockEntity extends Entity {
|
||||
ResourceKey<Level> oldDimension = this.level().dimension();
|
||||
boolean fromOrToEnd = (oldDimension == Level.END || newDimension == Level.END) && oldDimension != newDimension;
|
||||
Entity newEntity = super.teleport(transition);
|
||||
- this.forceTickAfterTeleportToDuplicate = newEntity != null && fromOrToEnd && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper
|
||||
+ this.forceTickAfterTeleportToDuplicate = newEntity != null && fromOrToEnd && (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation || me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled); // Paper // Luminol - Unsafe teleportation
|
||||
return newEntity;
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
index d42bb2a1721e4ab8c9956e18c3ca418b8d648c59..4f06daf619596d4116140b0710ea92c2c8552fc0 100644
|
||||
--- a/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
+++ b/net/minecraft/world/level/block/EndPortalBlock.java
|
||||
@@ -76,6 +76,12 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal {
|
||||
if (level.paperConfig().misc.disableEndCredits) {player.seenCredits = true; return;} // Paper - Option to disable end credits
|
||||
player.showEndCredits();
|
||||
} else {
|
||||
+ // Luminol start - unsafe teleportation
|
||||
+ if (me.earthme.luminol.config.modules.fixes.UnsafeTeleportationConfig.enabled && !(entity instanceof net.minecraft.world.entity.player.Player)) {
|
||||
+ entity.endPortalLogicAsync(pos);
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
entity.setAsInsidePortal(this, pos);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:04:06 +0800
|
||||
Subject: [PATCH] Add config for vanilla random
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index cf70a8e2fe2fe70bcdf71f8112479031d80d8b75..17650e196f1e5b79765651bf302291873a4eb509 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -298,7 +298,7 @@ public abstract class Entity
|
||||
public double yOld;
|
||||
public double zOld;
|
||||
public boolean noPhysics;
|
||||
- protected final RandomSource random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
|
||||
+ protected final RandomSource random = me.earthme.luminol.config.modules.fixes.VanillaRandomSourceConfig.useLegacyRandomSourceForPlayers ? RandomSource.create() : SHARED_RANDOM; // Paper - Share random for entities to make them more random // Luminol - Add config for vanilla random SHARED_RANDOM
|
||||
public int tickCount;
|
||||
private int remainingFireTicks;
|
||||
private final EntityFluidInteraction fluidInteraction = new EntityFluidInteraction(Set.of(FluidTags.WATER, FluidTags.LAVA));
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:12:26 +0800
|
||||
Subject: [PATCH] Add config for watchdog timeout
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/FoliaWatchdogThread.java b/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
|
||||
index e9ca1a15049b0211d10401cb78e953b93afaf6c7..fe1560579f9c9572082d52cf910f5916957f5601 100644
|
||||
--- a/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
|
||||
+++ b/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
|
||||
@@ -65,7 +65,7 @@ public final class FoliaWatchdogThread extends Thread {
|
||||
|
||||
for (final RunningTick tick : ticks) {
|
||||
final long elapsed = now - tick.lastPrint;
|
||||
- if (elapsed <= TimeUnit.SECONDS.toNanos(5L)) {
|
||||
+ if (elapsed <= TimeUnit.MILLISECONDS.toNanos(me.earthme.luminol.config.modules.misc.FoliaWatchogConfig.tickRegionTimeOutMs)) { // Luminol - Add config for watchdog timeout
|
||||
continue;
|
||||
}
|
||||
tick.lastPrint = now;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:10:51 +0800
|
||||
Subject: [PATCH] Add config to disable entity tick catchers
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index dc28223684091cd0d8dbf7ff01626b20e4f1b662..6fd7bfa561f71cfd043d7a1092d77b01bb320640 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -1591,6 +1591,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
), null, 1L);
|
||||
// Luminol end
|
||||
} catch (Throwable t) {
|
||||
+ if (me.earthme.luminol.config.modules.experiment.DisableEntityCatchConfig.enabled) throw t; // Luminol
|
||||
// Paper start - Prevent block entity and entity crashes
|
||||
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", io.papermc.paper.util.MCUtil.getLevelName(entity.level()), entity.getX(), entity.getY(), entity.getZ());
|
||||
MinecraftServer.LOGGER.error(msg, t);
|
||||
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:14:31 +0800
|
||||
Subject: [PATCH] Add config for heightmap warning
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/Heightmap.java b/net/minecraft/world/level/levelgen/Heightmap.java
|
||||
index dffa0d4859ecd7e21a9345f946083c56205145a3..21f0214992b82554c9532797cdc6fc593af1efe5 100644
|
||||
--- a/net/minecraft/world/level/levelgen/Heightmap.java
|
||||
+++ b/net/minecraft/world/level/levelgen/Heightmap.java
|
||||
@@ -128,7 +128,9 @@ public class Heightmap {
|
||||
if (rawData.length == data.length) {
|
||||
System.arraycopy(data, 0, rawData, 0, data.length);
|
||||
} else {
|
||||
- LOGGER.warn("Ignoring heightmap data for chunk {}, size does not match; expected: {}, got: {}", chunk.getPos(), rawData.length, data.length);
|
||||
+ // Luminol - Add config for heightmap warning
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableHeightmapWarning)
|
||||
+ LOGGER.warn("Ignoring heightmap data for chunk {}, size does not match; expected: {}, got: {}", chunk.getPos(), rawData.length, data.length); // Luminol - Add config for heightmap warning
|
||||
primeHeightmaps(chunk, EnumSet.of(type));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:15:04 +0800
|
||||
Subject: [PATCH] Add config gui support
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/dialog/action/ParsedTemplate.java b/net/minecraft/server/dialog/action/ParsedTemplate.java
|
||||
index 8a720ef5cd10bf04e97fb34c1ca0f0b265e98468..f1807523e1e6dbd13093f195c368b43a92b82af9 100644
|
||||
--- a/net/minecraft/server/dialog/action/ParsedTemplate.java
|
||||
+++ b/net/minecraft/server/dialog/action/ParsedTemplate.java
|
||||
@@ -13,7 +13,7 @@ public class ParsedTemplate {
|
||||
private final String raw;
|
||||
private final StringTemplate parsed;
|
||||
|
||||
- private ParsedTemplate(final String raw, final StringTemplate parsed) {
|
||||
+ public ParsedTemplate(final String raw, final StringTemplate parsed) { // Luminol - make public
|
||||
this.raw = raw;
|
||||
this.parsed = parsed;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:15:22 +0800
|
||||
Subject: [PATCH] Add force the data command to be enabled config
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index bc9f6cc286536b87513de81855ad0b61cf787c84..afbaf2116930d72ebb0c77745d02115abab14dc4 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -202,7 +202,9 @@ public class Commands {
|
||||
ClearInventoryCommands.register(this.dispatcher, context);
|
||||
//CloneCommands.register(this.dispatcher, context); // Folia - region threading - TODO
|
||||
DamageCommand.register(this.dispatcher, context);
|
||||
- //DataCommands.register(this.dispatcher); // Folia - region threading - TODO
|
||||
+ if(me.earthme.luminol.config.modules.experiment.CommandConfig.data) { // Luminol - Config for data command
|
||||
+ DataCommands.register(this.dispatcher); // Folia - region threading - TODO // Luminol - Config for data command
|
||||
+ } // Luminol - Config for data command
|
||||
//DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
||||
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
|
||||
DefaultGameModeCommands.register(this.dispatcher);
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:15:32 +0800
|
||||
Subject: [PATCH] Add experimental config for command block command execution
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/BaseCommandBlock.java b/net/minecraft/world/level/BaseCommandBlock.java
|
||||
index 31f1583f29eebe5e13b5a7ac5116fdafc3592e5c..47fe63e49a7cfb77f8fe5cc95ab9faf46d244ba9 100644
|
||||
--- a/net/minecraft/world/level/BaseCommandBlock.java
|
||||
+++ b/net/minecraft/world/level/BaseCommandBlock.java
|
||||
@@ -91,7 +91,7 @@ public abstract class BaseCommandBlock {
|
||||
}
|
||||
|
||||
public boolean performCommand(final ServerLevel level) {
|
||||
- if (true) return false; // Folia - region threading
|
||||
+ if (!me.earthme.luminol.config.modules.experiment.CommandConfig.commandBlock) return false; // Folia - region threading // Luminol - Add experimental config for command block command execution
|
||||
if (level.getGameTime() == this.lastExecution) {
|
||||
return false;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:16:40 +0800
|
||||
Subject: [PATCH] Add config to verify signature only in online-mode
|
||||
|
||||
Co-authored-by: Stabrinai <wujiaxin752@outlook.com>
|
||||
|
||||
diff --git a/net/minecraft/world/entity/player/ProfilePublicKey.java b/net/minecraft/world/entity/player/ProfilePublicKey.java
|
||||
index 5e29a9de070e9922513e972254fc7ec43e8774f2..2de1886f9d9f06f8b92755e8421c176679e8b5ce 100644
|
||||
--- a/net/minecraft/world/entity/player/ProfilePublicKey.java
|
||||
+++ b/net/minecraft/world/entity/player/ProfilePublicKey.java
|
||||
@@ -23,7 +23,7 @@ public record ProfilePublicKey(ProfilePublicKey.Data data) {
|
||||
public static final Codec<ProfilePublicKey> TRUSTED_CODEC = ProfilePublicKey.Data.CODEC.xmap(ProfilePublicKey::new, ProfilePublicKey::data);
|
||||
|
||||
public static ProfilePublicKey createValidated(final SignatureValidator validator, final UUID profileId, final ProfilePublicKey.Data data) throws ProfilePublicKey.ValidationException {
|
||||
- if (!data.validateSignature(validator, profileId)) {
|
||||
+ if (!data.validateSignature(validator, profileId) && (org.bukkit.Bukkit.getServer().getOnlineMode() && me.earthme.luminol.config.modules.misc.PublickeyVerifyConfig.enabled)) { // Luminol - Verify signature only in online-mode
|
||||
throw new ProfilePublicKey.ValidationException(INVALID_SIGNATURE, org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PUBLIC_KEY_SIGNATURE); // Paper - kick event causes
|
||||
} else {
|
||||
return new ProfilePublicKey(data);
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:17:02 +0800
|
||||
Subject: [PATCH] Add config for whether to save portal tickets
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/TicketType.java b/net/minecraft/server/level/TicketType.java
|
||||
index 7e612e03087d63f9b500f7e9f3442b1931bae7ee..083a82b5200a251e85f155d1df016cd8b4f18db5 100644
|
||||
--- a/net/minecraft/server/level/TicketType.java
|
||||
+++ b/net/minecraft/server/level/TicketType.java
|
||||
@@ -60,7 +60,7 @@ public final class TicketType<T> implements ca.spottedleaf.moonrise.patches.chun
|
||||
public static final TicketType PLAYER_LOADING = register("player_loading", NO_TIMEOUT, FLAG_LOADING);
|
||||
public static final TicketType PLAYER_SIMULATION = register("player_simulation", NO_TIMEOUT, FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE);
|
||||
public static final TicketType FORCED = register("forced", NO_TIMEOUT, FLAG_PERSIST | FLAG_LOADING | FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE);
|
||||
- public static final TicketType PORTAL = register("portal", 300L, FLAG_PERSIST | FLAG_LOADING | FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE);
|
||||
+ public static final TicketType PORTAL = register("portal", 300L, me.earthme.luminol.config.modules.misc.SavePortalTicketsConfig.doSave ? FLAG_PERSIST | FLAG_LOADING | FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE : FLAG_LOADING | FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE);
|
||||
public static final TicketType ENDER_PEARL = register("ender_pearl", 40L, FLAG_LOADING | FLAG_SIMULATION | FLAG_KEEP_DIMENSION_ACTIVE);
|
||||
public static final TicketType UNKNOWN = register("unknown", 1L, FLAG_CAN_EXPIRE_IF_UNLOADED | FLAG_LOADING);
|
||||
public static final TicketType PLUGIN = register("plugin", NO_TIMEOUT, FLAG_LOADING | FLAG_SIMULATION); // CraftBukkit
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 09:18:31 +0800
|
||||
Subject: [PATCH] Add back read-only datapack command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index afbaf2116930d72ebb0c77745d02115abab14dc4..6823c41c08ca1a1baf9257fc861ae97bbcbe3a50 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -205,7 +205,7 @@ public class Commands {
|
||||
if(me.earthme.luminol.config.modules.experiment.CommandConfig.data) { // Luminol - Config for data command
|
||||
DataCommands.register(this.dispatcher); // Folia - region threading - TODO // Luminol - Config for data command
|
||||
} // Luminol - Config for data command
|
||||
- //DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
||||
+ DataPackCommand.register(this.dispatcher, context); // Folia - region threading - TODO // Luminol - Add back read-only datapack command
|
||||
//DebugCommand.register(this.dispatcher); // Folia - region threading - TODO
|
||||
DefaultGameModeCommands.register(this.dispatcher);
|
||||
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
|
||||
diff --git a/net/minecraft/server/commands/DataPackCommand.java b/net/minecraft/server/commands/DataPackCommand.java
|
||||
index 0da1e4ada8616af825ddd4678e61246c672f9c4f..80d9bc3d680c30dae15064e0e8c3d1379ccd52e6 100644
|
||||
--- a/net/minecraft/server/commands/DataPackCommand.java
|
||||
+++ b/net/minecraft/server/commands/DataPackCommand.java
|
||||
@@ -99,7 +99,7 @@ public class DataPackCommand {
|
||||
dispatcher.register(
|
||||
Commands.literal("datapack")
|
||||
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
|
||||
- .then(
|
||||
+ /*.then( // Luminol - Add back read-only datapack command
|
||||
Commands.literal("enable")
|
||||
.then(
|
||||
Commands.argument("name", StringArgumentType.string())
|
||||
@@ -146,11 +146,11 @@ public class DataPackCommand {
|
||||
.suggests(SELECTED_PACKS)
|
||||
.executes(c -> disablePack(c.getSource(), getPack(c, "name", false)))
|
||||
)
|
||||
- )
|
||||
+ )*/ // Luminol - Add back read-only datapack command
|
||||
.then(
|
||||
Commands.literal("list")
|
||||
.executes(c -> listPacks(c.getSource()))
|
||||
- .then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource())))
|
||||
+ //.then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource()))) // Luminol - Add back read-only datapack command
|
||||
.then(Commands.literal("enabled").executes(c -> listEnabledPacks(c.getSource())))
|
||||
)
|
||||
.then(
|
||||
@@ -238,12 +238,12 @@ public class DataPackCommand {
|
||||
}
|
||||
|
||||
private static int listPacks(final CommandSourceStack source) {
|
||||
- return listEnabledPacks(source) + listAvailablePacks(source);
|
||||
+ return listEnabledPacks(source) ;// + listAvailablePacks(source); // Luminol - Add back read-only datapack command
|
||||
}
|
||||
|
||||
private static int listAvailablePacks(final CommandSourceStack source) {
|
||||
PackRepository repository = source.getServer().getPackRepository();
|
||||
- repository.reload();
|
||||
+ //repository.reload(); // Luminol - Add back read-only datapack command
|
||||
Collection<Pack> selectedPacks = repository.getSelectedPacks();
|
||||
Collection<Pack> availablePacks = repository.getAvailablePacks();
|
||||
FeatureFlagSet enabledFeatures = source.enabledFeatures();
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:16:33 +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
|
||||
index 52dcbcf64c3a510d4a4524b7d0ee226d9a73511d..051d601e7e809518e8d82ae4ae3259054d704f51 100644
|
||||
--- a/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
|
||||
+++ b/ca/spottedleaf/moonrise/paper/util/BaseChunkSystemHooks.java
|
||||
@@ -122,6 +122,7 @@ public abstract class BaseChunkSystemHooks implements ca.spottedleaf.moonrise.co
|
||||
|
||||
@Override
|
||||
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||
+ chunk.getChunkHot().clear(); // KioCG
|
||||
chunk.getLevel().getCurrentWorldData().removeTickingChunk(chunk); // Folia - region threading
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index d4e31bb829451a687bf567fd0357f46fd7d46902..350b788e17dc49118498541ad8ac54f6e0a59c9d 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1743,7 +1743,46 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// Folia end - region threading
|
||||
//this.tickCount++; // Folia - region threading
|
||||
//this.tickRateManager.tick(); // Folia - region threading
|
||||
+ // KioCG start - ChunkHot
|
||||
+ final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.level.chunk.LevelChunk> chunks = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>();
|
||||
+ if (region != null){
|
||||
+ for (net.minecraft.world.level.chunk.LevelChunk chunk : region.world.getCurrentWorldData().getTickingChunks()) {
|
||||
+ /* wait for rewrite - temporarily crash fix
|
||||
+ for (net.minecraft.server.level.ServerChunkCache.ChunkAndHolder chunkAndHolder : region.world.getCurrentWorldData().getTickingChunks()){
|
||||
+ final net.minecraft.world.level.chunk.LevelChunk chunk = chunkAndHolder.chunk();
|
||||
+ */
|
||||
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(region.world, chunk.locX, chunk.locZ)){
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ chunks.add(chunk);
|
||||
+ }
|
||||
+ }
|
||||
+ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
|
||||
+ final java.util.Iterator<net.minecraft.world.level.chunk.LevelChunk> chunkIterator = chunks.unsafeIterator();
|
||||
+ while (chunkIterator.hasNext()){
|
||||
+ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
|
||||
+
|
||||
+ targetChunk.getChunkHot().nextTick();
|
||||
+ targetChunk.getChunkHot().start();
|
||||
+ }
|
||||
+ }
|
||||
+ //KioCG end
|
||||
this.tickChildren(haveTime, region); // Folia - region threading
|
||||
+ // KioCG start - ChunkHot
|
||||
+ if (region != null && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % 20 == 0){
|
||||
+ final java.util.Iterator<net.minecraft.world.level.chunk.LevelChunk> chunkIterator = chunks.unsafeIterator();
|
||||
+ while (chunkIterator.hasNext()){
|
||||
+ final net.minecraft.world.level.chunk.LevelChunk targetChunk = chunkIterator.next();
|
||||
+
|
||||
+ if (!targetChunk.getChunkHot().isStarted()){
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ targetChunk.getChunkHot().stop();
|
||||
+ }
|
||||
+ }
|
||||
+ //KioCG end
|
||||
if (false && nano - this.lastServerStatus >= STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading
|
||||
this.lastServerStatus = nano;
|
||||
this.status = this.buildServerStatus();
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 0641b98ef3298eb682ceae83f60b730f3bf90103..cea4bc7036dfd8777c151a0dd811fc13579d6501 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1491,6 +1491,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
public void tickNonPassenger(final Entity entity) {
|
||||
// Paper start - log detailed entity tick information
|
||||
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
|
||||
+ LevelChunk levelChunk = entity.shouldTickHot() ? this.getChunkIfLoaded(entity.moonrise$getSectionX(),entity.moonrise$getSectionZ()) : null; // KioCG
|
||||
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
|
||||
try {
|
||||
// Folia - region threading
|
||||
// Paper end - log detailed entity tick information
|
||||
@@ -1552,6 +1554,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
} finally {
|
||||
// Folia - region threading
|
||||
}
|
||||
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
|
||||
// Paper end - log detailed entity tick information
|
||||
}
|
||||
|
||||
@@ -1563,6 +1566,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
final int timerId = isActive ? entity.getType().tickTimerId : entity.getType().inactiveTickTimerId;
|
||||
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler();
|
||||
foliaProfiler.startTimer(timerId);
|
||||
+ LevelChunk levelChunk = !(entity instanceof Player) ? this.getChunkIfLoaded(entity.blockPosition()) : null; // KioCG
|
||||
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
|
||||
try {
|
||||
// Folia end - profiler
|
||||
entity.setOldPosAndRot();
|
||||
@@ -1597,6 +1602,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
this.tickPassenger(entity, passenger, isActive); // Paper - EAR 2
|
||||
}
|
||||
} finally { foliaProfiler.stopTimer(timerId); } // Folia - profiler
|
||||
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index ab6229ee412cf2aa5affc87510230c587765080b..f0c574e039f80ff0227239356de8d61ef06a0936 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -441,7 +441,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public boolean isRealPlayer; // Paper
|
||||
public com.destroystokyo.paper.event.entity.@Nullable PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent
|
||||
public org.bukkit.event.player.PlayerQuitEvent.@Nullable 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();
|
||||
@@ -889,6 +891,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
+ // Luminol start - Status bars
|
||||
+ this.statusBarList.tick();
|
||||
+ // Luminol end - Status bars
|
||||
// CraftBukkit start
|
||||
if (this.joining) {
|
||||
this.joining = false;
|
||||
@@ -949,8 +954,35 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.trackEnteredOrExitedLavaOnVehicle();
|
||||
this.updatePlayerAttributes();
|
||||
this.advancements.flushDirty(this, true);
|
||||
+
|
||||
+ // KioCG start - ChunkHot
|
||||
+ if (this.tickCount % 20 == 0){
|
||||
+ this.nearbyChunkHot = this.refreshNearbyChunkHot();
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
|
||||
+ // KioCG start - ChunkHot
|
||||
+ private volatile long nearbyChunkHot = 0;
|
||||
+
|
||||
+ public long getNearbyChunkHot() { return this.nearbyChunkHot; }
|
||||
+
|
||||
+ private long refreshNearbyChunkHot() {
|
||||
+ long total = 0L;
|
||||
+ int searchRadius = ((ServerLevel) this.level()).moonrise$getViewDistanceHolder().getViewDistances().tickViewDistance();
|
||||
+ for (int i = this.moonrise$getSectionX() - searchRadius; i <= this.moonrise$getSectionX() + searchRadius; ++i) {
|
||||
+ for (int j = this.moonrise$getSectionZ() - searchRadius; j <= this.moonrise$getSectionZ() + searchRadius; ++j) {
|
||||
+ net.minecraft.world.level.chunk.LevelChunk targetChunk = this.level().getChunkIfLoaded(i, j);
|
||||
+ if (targetChunk != null) {
|
||||
+ total += targetChunk.getChunkHot().getAverage();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return total;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
+
|
||||
+
|
||||
private void updatePlayerAttributes() {
|
||||
AttributeInstance blockInteractionRange = this.getAttribute(Attributes.BLOCK_INTERACTION_RANGE);
|
||||
if (blockInteractionRange != null) {
|
||||
diff --git a/net/minecraft/world/entity/AreaEffectCloud.java b/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
index f03fa06c0ba56f7f5e1e45bc1568a490751efde3..eee1c14249addbf4714df733870da9747bda2245 100644
|
||||
--- a/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
@@ -415,4 +415,11 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
|
||||
return super.applyImplicitComponent(type, value);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 17650e196f1e5b79765651bf302291873a4eb509..f218b7f6ce32d7ac959255e59c620d6fd420bf8e 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -6468,4 +6468,6 @@ public abstract class Entity
|
||||
return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition());
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/LightningBolt.java b/net/minecraft/world/entity/LightningBolt.java
|
||||
index 5b19fee8a4861e5dbfb545bbe4dabda7787c430a..0afca6f5f5b02609fd55e9ea4d72b8862cc03420 100644
|
||||
--- a/net/minecraft/world/entity/LightningBolt.java
|
||||
+++ b/net/minecraft/world/entity/LightningBolt.java
|
||||
@@ -283,4 +283,11 @@ public class LightningBolt extends Entity {
|
||||
public final boolean hurtServer(final ServerLevel level, final DamageSource source, final float damage) {
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 9c8e8de53cbbd87ac7cb8483bd3c1af3fcf66b6e..301e75393d1074eca0c8533219f516b6d625a38a 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -1735,4 +1735,11 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
public float chargeSpeedModifier() {
|
||||
return 1.0F;
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return super.shouldTickHot() && (!this.removeWhenFarAway(0.0) || this.isPersistenceRequired() || this.requiresCustomPersistence());
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/equine/TraderLlama.java b/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
||||
index 7c92c9335997cee76ff360c51f704ee41a180796..fb4cab83fd23c5561326a58683558e9a4219b0e9 100644
|
||||
--- a/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
||||
+++ b/net/minecraft/world/entity/animal/equine/TraderLlama.java
|
||||
@@ -164,4 +164,11 @@ public class TraderLlama extends Llama {
|
||||
super.start();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return super.shouldTickHot() && !this.canDespawn();
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
||||
index f79353aa58b03d00839e4e95d1fd2480a635a592..0a43947bcc9f505ad9bc4d54c564709c2c3e411a 100644
|
||||
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
||||
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTrader.java
|
||||
@@ -271,4 +271,11 @@ public class WanderingTrader extends AbstractVillager implements Consumable.Over
|
||||
return !pos.closerToCenterThan(this.trader.position(), distance);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index 2eb5fc819e2e17c69de87f8aa1a99e02bc5a62d5..a4bc767b799c050ce07a3685f655b4ba947d2466 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -170,6 +170,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
private ItemStack lastItemInMainHand = ItemStack.EMPTY;
|
||||
private final ItemCooldowns cooldowns = this.createItemCooldowns();
|
||||
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
|
||||
+ public me.earthme.luminol.functions.bars.TickableStatusBarList statusBarList = new me.earthme.luminol.functions.bars.TickableStatusBarList(this); // Luminol status bars
|
||||
public @Nullable FishingHook fishing;
|
||||
public float hurtDir;
|
||||
public boolean affectsSpawning = true; // Paper - Affects Spawning API
|
||||
@@ -679,6 +680,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.abilities.getWalkingSpeed());
|
||||
this.enderChestInventory.fromSlots(input.listOrEmpty("EnderItems", ItemStackWithSlot.CODEC));
|
||||
this.setLastDeathLocation(input.read("LastDeathLocation", GlobalPos.CODEC));
|
||||
+ this.statusBarList.load(input); // Luminol - Status bars
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -697,6 +699,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
output.store("abilities", Abilities.Packed.CODEC, this.abilities.pack());
|
||||
this.enderChestInventory.storeAsSlots(output.list("EnderItems", ItemStackWithSlot.CODEC));
|
||||
this.lastDeathLocation.ifPresent(pos -> output.store("LastDeathLocation", GlobalPos.CODEC, pos));
|
||||
+ this.statusBarList.save(output); // Luminol - Status bars
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2255,4 +2258,12 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
public static final Player.BedSleepingProblem NOT_SAFE = new Player.BedSleepingProblem(Component.translatable("block.minecraft.bed.not_safe"));
|
||||
public static final Player.BedSleepingProblem EXPLOSION = new Player.BedSleepingProblem(null); // Paper - Added to properly handle explosions in bed events
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
+
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index 67d01bb84cd40a3f67de441e9dbdc2ac7638cada..721e3b083846fd363a31311196bc4c681969215c 100644
|
||||
--- a/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -512,4 +512,11 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
public interface ProjectileFactory<T extends Projectile> {
|
||||
T create(final ServerLevel level, LivingEntity entity, ItemStack itemStack);
|
||||
}
|
||||
+
|
||||
+ // KioCG start
|
||||
+ @Override
|
||||
+ public boolean shouldTickHot() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // KioCG end
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 64e0c4a60a74cd33f2b99f34fa2a419abf3a0c02..0e84b695a677e71f443a29c78fc5025eec7ae7f4 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -112,6 +112,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
// Paper start - rewrite chunk system
|
||||
private boolean postProcessingDone;
|
||||
private ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkAndHolder;
|
||||
+ private final com.kiocg.ChunkHot chunkHot = new com.kiocg.ChunkHot(); public com.kiocg.ChunkHot getChunkHot() { return this.chunkHot; } // KioCG
|
||||
|
||||
@Override
|
||||
public final boolean moonrise$isPostProcessingDone() {
|
||||
@@ -960,6 +961,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push(this::getType);
|
||||
foliaProfiler.startTimer(timerId); try { // Folia - profiler
|
||||
+ LevelChunk.this.chunkHot.startTicking(); // KioCG
|
||||
BlockState blockState = LevelChunk.this.getBlockState(pos);
|
||||
if (this.blockEntity.getType().isValid(blockState)) {
|
||||
this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity);
|
||||
@@ -979,7 +981,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
);
|
||||
} // Paper - Remove the Block Entity if it's invalid
|
||||
}
|
||||
- } finally { foliaProfiler.stopTimer(timerId); } // Folia - profiler
|
||||
+ } finally { foliaProfiler.stopTimer(timerId); LevelChunk.this.chunkHot.stopTickingAndCount(); } // Folia - profiler // KioCG
|
||||
|
||||
profiler.pop();
|
||||
} catch (Throwable t) {
|
||||
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
index 041ed95948ff6bb4cf3610ce4522a6ba105b6812..44dbe6f83c8593c213132feabc7fe27615cb0049 100644
|
||||
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
|
||||
@@ -81,7 +81,10 @@ public interface NeighborUpdater {
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ net.minecraft.world.level.chunk.LevelChunk levelChunk = level.getChunkIfLoaded(pos); // KioCG
|
||||
+ if (levelChunk != null) levelChunk.getChunkHot().startTicking(); try { // KioCG
|
||||
state.handleNeighborChanged(level, pos, changedBlock, orientation, movedByPiston);
|
||||
+ } finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
|
||||
// Spigot start
|
||||
} catch (StackOverflowError ex) {
|
||||
level.lastPhysicsProblem = pos.immutable();
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:30:46 +0800
|
||||
Subject: [PATCH] Add config to modify tripwire behavior
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index 8bcc8b6f83ab4d5a472741185511b5d84f4974be..49b3f9e78ae9db257b653a6094619880784c6370 100644
|
||||
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -201,10 +201,17 @@ public class TripWireHookBlock extends Block {
|
||||
BlockPos testPos = pos.relative(direction, i);
|
||||
BlockState wireData = wireStates[i];
|
||||
if (wireData != null) {
|
||||
- BlockState testPosState = level.getBlockState(testPos);
|
||||
- if (testPosState.is(Blocks.TRIPWIRE) || testPosState.is(Blocks.TRIPWIRE_HOOK)) {
|
||||
- if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !testPosState.is(Blocks.TRIPWIRE)) level.setBlock(testPos, wireData.trySetValue(ATTACHED, attached), Block.UPDATE_ALL); // Paper - prevent tripwire from updating
|
||||
+ // Luminol start - tripwire and tripwireHook dupe
|
||||
+ if (me.earthme.luminol.config.modules.function.TripwireBehaviorConfig.enabled) {
|
||||
+ level.setBlock(testPos, wireData.trySetValue(ATTACHED, attached), 3);
|
||||
+ level.getBlockState(testPos);
|
||||
+ } else {
|
||||
+ BlockState testPosState = level.getBlockState(testPos);
|
||||
+ if (testPosState.is(Blocks.TRIPWIRE) || testPosState.is(Blocks.TRIPWIRE_HOOK)) {
|
||||
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !testPosState.is(Blocks.TRIPWIRE)) level.setBlock(testPos, wireData.trySetValue(ATTACHED, attached), Block.UPDATE_ALL); // Paper - prevent tripwire from updating
|
||||
+ }
|
||||
}
|
||||
+ // Luminol end - tripwire and tripwireHook dupe
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java b/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
|
||||
index b67f5f7b76037ab77548c37a83e4d0918915223a..a8e69343f47ba2383f9dcc2cf6328463892aaeec 100644
|
||||
--- a/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
|
||||
+++ b/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
|
||||
@@ -28,14 +28,39 @@ public class EndPlatformFeature extends Feature<NoneFeatureConfiguration> {
|
||||
// CraftBukkit end
|
||||
BlockPos.MutableBlockPos pos = origin.mutable();
|
||||
|
||||
- for (int dz = -2; dz <= 2; dz++) {
|
||||
+ // Luminol start - tripwire behavior modifier
|
||||
+ java.util.List<BlockPos> blockList1 = new java.util.ArrayList<>();
|
||||
+ java.util.List<BlockPos> blockList2 = new java.util.ArrayList<>();
|
||||
+ boolean flag21 = me.earthme.luminol.config.modules.function.TripwireBehaviorConfig.behaviorMode == me.earthme.luminol.enums.EnumTripwireBehavior.VANILLA21; for (int dz = -2; dz <= 2; dz++) {
|
||||
for (int dx = -2; dx <= 2; dx++) {
|
||||
for (int dy = -1; dy < 3; dy++) {
|
||||
BlockPos blockPos = pos.set(origin).move(dx, dy, dz);
|
||||
Block block = dy == -1 ? Blocks.OBSIDIAN : Blocks.AIR;
|
||||
if (!blockList.getBlockState(blockPos).is(block)) { // CraftBukkit
|
||||
if (dropResources) {
|
||||
- blockList.destroyBlock(blockPos, true, null); // CraftBukkit
|
||||
+ boolean flag = false;
|
||||
+ if (me.earthme.luminol.config.modules.function.TripwireBehaviorConfig.enabled) {
|
||||
+ switch (me.earthme.luminol.config.modules.function.TripwireBehaviorConfig.behaviorMode) {
|
||||
+ case me.earthme.luminol.enums.EnumTripwireBehavior.VANILLA20: {
|
||||
+ flag = true;
|
||||
+ }
|
||||
+ case me.earthme.luminol.enums.EnumTripwireBehavior.MIXED: {
|
||||
+ net.minecraft.world.level.block.state.BlockState state = newLevel.getBlockState(blockPos);
|
||||
+ if (state.is(Blocks.TRIPWIRE)) {
|
||||
+ if (state.getValue(net.minecraft.world.level.block.TripWireBlock.DISARMED)) {
|
||||
+ flag = true;
|
||||
+ blockList2.add(blockPos.immutable());
|
||||
+ }
|
||||
+ if (!flag) {
|
||||
+ flag = checkString(blockList2, blockPos);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ default: {} // Luminol - 1.21 & default Logic - default empty
|
||||
+ }
|
||||
+ }
|
||||
+ if (flag) blockList1.add(blockPos.immutable());
|
||||
+ else blockList.destroyBlock(blockPos, true, null); // CraftBukkit
|
||||
}
|
||||
|
||||
blockList.setBlock(blockPos, block.defaultBlockState(), Block.UPDATE_ALL); // CraftBukkit
|
||||
@@ -53,11 +78,30 @@ public class EndPlatformFeature extends Feature<NoneFeatureConfiguration> {
|
||||
if (portalEvent.isCancelled()) return;
|
||||
}
|
||||
|
||||
- if (dropResources) {
|
||||
- blockList.placeBlocks(state -> newLevel.destroyBlock(state.getPosition(), true, null));
|
||||
+ if (flag21 || !me.earthme.luminol.config.modules.function.TripwireBehaviorConfig.enabled) {
|
||||
+ if (dropResources) {
|
||||
+ blockList.placeBlocks(state -> newLevel.destroyBlock(state.getPosition(), true, null));
|
||||
+ } else {
|
||||
+ blockList.placeBlocks();
|
||||
+ }
|
||||
} else {
|
||||
+ if (dropResources) {
|
||||
+ blockList.getSnapshotBlocks().forEach((state) -> {
|
||||
+ newLevel.destroyBlock(state.getPosition(), !blockList1.contains(state.getPosition()), null);
|
||||
+ });
|
||||
+ // Luminol - prevent tripwire dupe in end platform generate
|
||||
+ }
|
||||
blockList.placeBlocks();
|
||||
}
|
||||
// CraftBukkit end
|
||||
}
|
||||
+
|
||||
+ private static boolean checkString(java.util.List<BlockPos> blockList, BlockPos blockPos) {
|
||||
+ for (BlockPos pos : blockList) {
|
||||
+ if (pos.getY() != blockPos.getY()) continue;
|
||||
+ if (pos.getX() == blockPos.getX() || pos.getZ() == blockPos.getZ()) return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol end - tripwire behavior modifier
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Fri, 5 Jun 2026 15:09:29 +0800
|
||||
Subject: [PATCH] Add config to enable tick command
|
||||
|
||||
only freeze/unfreeze/step/query can run when enabled
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
index ff90abb47203c03636d3175f2b3efcf43517b3b0..276349d778c2e6f0b1081eec4851bad5d25db237 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
|
||||
@@ -239,6 +239,11 @@ public final class RegionizedServer {
|
||||
|
||||
private void globalTick(final long tickCount) {
|
||||
++this.tickCount;
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
|
||||
+ MinecraftServer.getServer().tickRateManager().tick();
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
// expire invalid click command callbacks
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
|
||||
@@ -415,7 +420,7 @@ public final class RegionizedServer {
|
||||
}
|
||||
|
||||
private void tickTime(final ServerLevel world, final long tickCount) {
|
||||
- if (world.tickTime) {
|
||||
+ if ((!me.earthme.luminol.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command
|
||||
world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + tickCount);
|
||||
}
|
||||
}
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
index 58e557923dfe6cee39ec45e7f5aa43a5ded9f107..5f4f80c1d4003254fd840f71d86908603b57bfa2 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java
|
||||
@@ -559,6 +559,11 @@ public final class TickRegionScheduler {
|
||||
try {
|
||||
// next start isn't updated until the end of this tick
|
||||
this.tickRegion(tickCount, tickStart, scheduledEnd);
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
|
||||
+ MinecraftServer.getServer().tickRateManager().endTickWork();
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
} catch (final Throwable thr) {
|
||||
this.scheduler.regionFailed(this, false, thr);
|
||||
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 6823c41c08ca1a1baf9257fc861ae97bbcbe3a50..0fa14f60310b063f419620539fd40898627b46b9 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -259,7 +259,11 @@ public class Commands {
|
||||
TeleportCommand.register(this.dispatcher);
|
||||
TellRawCommand.register(this.dispatcher, context);
|
||||
//TestCommand.register(this.dispatcher, context); // Folia - region threading
|
||||
- //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ // Luminol start - Add a config to enable tick command
|
||||
+ if (me.earthme.luminol.config.modules.experiment.CommandConfig.tick) {
|
||||
+ TickCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
+ }
|
||||
+ // Luminol end - Add a config to enable tick command
|
||||
TimeCommand.register(this.dispatcher, context);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
diff --git a/net/minecraft/server/commands/TickCommand.java b/net/minecraft/server/commands/TickCommand.java
|
||||
index e8d6a67143f3f0b4813e51bb273498bc404899b9..64b685b219b930a1bb7f85db9947f4d1ca9df093 100644
|
||||
--- a/net/minecraft/server/commands/TickCommand.java
|
||||
+++ b/net/minecraft/server/commands/TickCommand.java
|
||||
@@ -23,14 +23,14 @@ public class TickCommand {
|
||||
Commands.literal("tick")
|
||||
.requires(Commands.hasPermission(Commands.LEVEL_ADMINS))
|
||||
.then(Commands.literal("query").executes(c -> tickQuery(c.getSource())))
|
||||
- .then(
|
||||
+/* .then(
|
||||
Commands.literal("rate")
|
||||
.then(
|
||||
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
|
||||
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, b))
|
||||
.executes(c -> setTickingRate(c.getSource(), FloatArgumentType.getFloat(c, "rate")))
|
||||
)
|
||||
- )
|
||||
+ )*/
|
||||
.then(
|
||||
Commands.literal("step")
|
||||
.executes(c -> step(c.getSource(), 1))
|
||||
@@ -41,7 +41,7 @@ public class TickCommand {
|
||||
.executes(c -> step(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
|
||||
)
|
||||
)
|
||||
- .then(
|
||||
+/* .then(
|
||||
Commands.literal("sprint")
|
||||
.then(Commands.literal("stop").executes(c -> stopSprinting(c.getSource())))
|
||||
.then(
|
||||
@@ -49,7 +49,7 @@ public class TickCommand {
|
||||
.suggests((c, b) -> SharedSuggestionProvider.suggest(new String[]{"60s", "1d", "3d"}, b))
|
||||
.executes(c -> sprint(c.getSource(), IntegerArgumentType.getInteger(c, "time")))
|
||||
)
|
||||
- )
|
||||
+ )*/
|
||||
.then(Commands.literal("unfreeze").executes(c -> setFreeze(c.getSource(), false)))
|
||||
.then(Commands.literal("freeze").executes(c -> setFreeze(c.getSource(), true)))
|
||||
);
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Libalpm64 <Levamara@proton.me>
|
||||
Date: Wed, 4 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] Add config for item multitask
|
||||
|
||||
Allows players to use items while moving or switching hotbar slots. This
|
||||
is for Anarchy servers or Crystal PVP servers this allows them to pvp
|
||||
without stopping the item mid animation.
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 1ea8e03a4dc39486505d21bff1d15cb2339cafc2..a2146662c8ec83f62547bcd813c0e4dcb10efc07 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2186,7 +2186,9 @@ public class ServerGamePacketListenerImpl
|
||||
this.player.sendSpawnProtectionMessage(pos);
|
||||
} else if (this.awaitingPositionFromClient == null && (level.mayInteract(this.player, pos) || passthroughSignInteraction)) {
|
||||
// Paper end - Allow using signs inside spawn protection
|
||||
+ if (!me.earthme.luminol.config.modules.fixes.ItemMultitaskConfig.enabled) { // Luminol - Add item multitask config
|
||||
this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706
|
||||
+ } // Luminol - Add item multitask config
|
||||
InteractionResult interactionResult = this.player.gameMode.useItemOn(this.player, level, itemStack, hand, blockHit);
|
||||
if (interactionResult.consumesAction()) {
|
||||
CriteriaTriggers.ANY_BLOCK_USE.trigger(this.player, blockHit.getBlockPos(), itemStack);
|
||||
@@ -2385,9 +2387,13 @@ public class ServerGamePacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- if (this.player.getInventory().getSelectedSlot() != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) {
|
||||
- this.player.stopUsingItem();
|
||||
+ // Luminol start - Add item multitask config
|
||||
+ if (!me.earthme.luminol.config.modules.fixes.ItemMultitaskConfig.enabled) {
|
||||
+ if (this.player.getInventory().getSelectedSlot() != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) {
|
||||
+ this.player.stopUsingItem();
|
||||
+ }
|
||||
}
|
||||
+ // Luminol end
|
||||
|
||||
this.player.getInventory().setSelectedSlot(packet.getSlot());
|
||||
this.player.resetLastActionTime();
|
||||
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 10:49:29 +0800
|
||||
Subject: [PATCH] Add tick regions api
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/ThreadedRegionizer.java b/io/papermc/paper/threadedregions/ThreadedRegionizer.java
|
||||
index 3449918b5001bb39c541ce1168eac4acf9144e1f..a346b96500ae859e9469c80e2ff6b39c4d3d0b52 100644
|
||||
--- a/io/papermc/paper/threadedregions/ThreadedRegionizer.java
|
||||
+++ b/io/papermc/paper/threadedregions/ThreadedRegionizer.java
|
||||
@@ -43,6 +43,7 @@ public final class ThreadedRegionizer<R extends ThreadedRegionizer.ThreadedRegio
|
||||
private final RegionCallbacks<R, S> callbacks;
|
||||
private final StampedLock regionLock = new StampedLock();
|
||||
private Thread writeLockOwner;
|
||||
+ public final me.earthme.luminol.api.ThreadedRegionizer threadedRegionizerAPI; // Luminol - Tick region API
|
||||
|
||||
/*
|
||||
static final record Operation(String type, int chunkX, int chunkZ) {}
|
||||
@@ -72,6 +73,7 @@ public final class ThreadedRegionizer<R extends ThreadedRegionizer.ThreadedRegio
|
||||
this.world = world;
|
||||
this.callbacks = callbacks;
|
||||
//this.loadTestData();
|
||||
+ this.threadedRegionizerAPI = new me.earthme.luminol.api.impl.ThreadedRegionizerImpl(this.world); // Luminol - Tick region API
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -693,6 +695,7 @@ public final class ThreadedRegionizer<R extends ThreadedRegionizer.ThreadedRegio
|
||||
|
||||
private final ReferenceOpenHashSet<ThreadedRegion<R, S>> mergeIntoLater = new ReferenceOpenHashSet<>();
|
||||
private final ReferenceOpenHashSet<ThreadedRegion<R, S>> expectingMergeFrom = new ReferenceOpenHashSet<>();
|
||||
+ public final me.earthme.luminol.api.ThreadedRegion threadedRegionAPI = new me.earthme.luminol.api.impl.ThreadedRegionImpl((ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>) this); // Luminol - Tickregion API
|
||||
|
||||
public ThreadedRegion(final ThreadedRegionizer<R, S> regioniser) {
|
||||
this.regioniser = regioniser;
|
||||
@@ -819,7 +822,7 @@ public final class ThreadedRegionizer<R extends ThreadedRegionizer.ThreadedRegio
|
||||
return this.deadSections.size() == this.sectionByKey.size();
|
||||
}
|
||||
|
||||
- private final double getDeadSectionPercent() {
|
||||
+ public final double getDeadSectionPercent() { // Luminol - Threaded regions api
|
||||
return (double)this.deadSections.size() / (double)this.sectionByKey.size();
|
||||
}
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/TickRegions.java b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
index a6ab9cb01f4f49f5f44b6ed324fa6d51139aabb6..97c514673a454b752ab86b944fd143725ca8090d 100644
|
||||
--- a/io/papermc/paper/threadedregions/TickRegions.java
|
||||
+++ b/io/papermc/paper/threadedregions/TickRegions.java
|
||||
@@ -156,6 +156,7 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
|
||||
private final AtomicInteger entityCount = new AtomicInteger();
|
||||
private final AtomicInteger playerCount = new AtomicInteger();
|
||||
private final AtomicInteger chunkCount = new AtomicInteger();
|
||||
+ public final me.earthme.luminol.api.RegionStats regionStatsAPI = new me.earthme.luminol.api.impl.RegionStatsImpl(this); // Luminol - Tickregion API
|
||||
|
||||
public int getEntityCount() {
|
||||
return this.entityCount.get();
|
||||
@@ -207,6 +208,7 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
|
||||
private final AtomicBoolean hasPackets = new AtomicBoolean(false);
|
||||
|
||||
public volatile ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler; // Folia - profiler
|
||||
+ public final me.earthme.luminol.api.TickRegionData tickRegionDataAPI = new me.earthme.luminol.api.impl.TickRegionDataImpl(this); // Luminol - Tickregion API
|
||||
|
||||
private TickRegionData(final ThreadedRegionizer.ThreadedRegion<TickRegionData, TickRegionSectionData> region) {
|
||||
this.region = region;
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 10:50:12 +0800
|
||||
Subject: [PATCH] Add missing teleportation event APIs for folia
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index f0c574e039f80ff0227239356de8d61ef06a0936..093c48e2379c01f45277b88f6c1b19b107a46326 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1814,6 +1814,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
if (finalRespawnCompleteCallback != null) { // Luminol - Level hot unload apis
|
||||
finalRespawnCompleteCallback.accept(ServerPlayer.this); // Luminol - Level hot unload apis
|
||||
}
|
||||
+ // Luminol - Add missing teleportation apis
|
||||
+ new me.earthme.luminol.api.entity.player.PostPlayerRespawnEvent(ServerPlayer.this.getBukkitEntity()).callEvent();
|
||||
+ // Luminol end
|
||||
}
|
||||
);
|
||||
});
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index f218b7f6ce32d7ac959255e59c620d6fd420bf8e..2ae0cf7c9a4febfa79a9eab2f0e9309a61a78f56 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4553,6 +4553,31 @@ public abstract class Entity
|
||||
// Luminol end
|
||||
|
||||
// TODO any events that can modify go HERE
|
||||
+ // Luminol start - Add missing teleportation apis
|
||||
+ org.bukkit.Location destinationLoc;
|
||||
+
|
||||
+ if (pitch == null) {
|
||||
+ if (yaw == null) {
|
||||
+ destinationLoc = io.papermc.paper.util.MCUtil.toLocation(destination, pos, Float.NaN, Float.NaN);
|
||||
+ } else {
|
||||
+ destinationLoc = io.papermc.paper.util.MCUtil.toLocation(destination, pos, yaw, Float.NaN);
|
||||
+ }
|
||||
+ }else {
|
||||
+ if (yaw == null) {
|
||||
+ destinationLoc = io.papermc.paper.util.MCUtil.toLocation(destination, pos, Float.NaN, pitch);
|
||||
+ }else {
|
||||
+ destinationLoc = io.papermc.paper.util.MCUtil.toLocation(destination, pos, yaw, pitch);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final me.earthme.luminol.api.entity.EntityTeleportAsyncEvent wrapped = new me.earthme.luminol.api.entity.EntityTeleportAsyncEvent(
|
||||
+ this.getBukkitEntity(),
|
||||
+ cause,
|
||||
+ destinationLoc
|
||||
+ );
|
||||
+
|
||||
+ wrapped.callEvent();
|
||||
+ // Luminol end
|
||||
|
||||
// check for same region
|
||||
if (destination == this.level()
|
||||
@@ -4671,6 +4696,17 @@ public abstract class Entity
|
||||
case END: {
|
||||
if (destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END) {
|
||||
BlockPos targetPos = ServerLevel.END_SPAWN_POINT;
|
||||
+ // Luminol start - Add missing teleportation apis
|
||||
+ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal);
|
||||
+ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, targetPos);
|
||||
+
|
||||
+ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent(
|
||||
+ orginalPortalLocation,
|
||||
+ targetPortalLocation
|
||||
+ );
|
||||
+
|
||||
+ portalLocateEvent.callEvent();
|
||||
+ // Luminol end
|
||||
// need to load chunks so we can create the platform
|
||||
destination.moonrise$loadChunksAsync(
|
||||
targetPos, 16, // load 16 blocks to be safe from block physics
|
||||
@@ -4696,6 +4732,17 @@ public abstract class Entity
|
||||
);
|
||||
} else {
|
||||
BlockPos spawnPos = destination.getRespawnData().pos();
|
||||
+ // Luminol start - Add missing teleportation apis
|
||||
+ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal);
|
||||
+ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, spawnPos);
|
||||
+
|
||||
+ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent(
|
||||
+ orginalPortalLocation,
|
||||
+ targetPortalLocation
|
||||
+ );
|
||||
+
|
||||
+ portalLocateEvent.callEvent();
|
||||
+ // Luminol end
|
||||
// need to load chunk for heightmap
|
||||
destination.moonrise$loadChunksAsync(
|
||||
spawnPos, 0,
|
||||
@@ -4751,7 +4798,17 @@ public abstract class Entity
|
||||
WorldBorder destinationBorder = destination.getWorldBorder();
|
||||
double dimensionScale = net.minecraft.world.level.dimension.DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType());
|
||||
BlockPos targetPos = destination.getWorldBorder().clampToBounds(this.getX() * dimensionScale, this.getY(), this.getZ() * dimensionScale);
|
||||
+ // Luminol start - Add missing teleportation apis
|
||||
+ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(origin, originPortal);
|
||||
+ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(destination, targetPos);
|
||||
|
||||
+ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent(
|
||||
+ orginalPortalLocation,
|
||||
+ targetPortalLocation
|
||||
+ );
|
||||
+
|
||||
+ portalLocateEvent.callEvent();
|
||||
+ // Luminol end
|
||||
ca.spottedleaf.concurrentutil.completable.CallbackCompletable<BlockUtil.FoundRectangle> portalFound
|
||||
= new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>();
|
||||
|
||||
@@ -4888,6 +4945,15 @@ public abstract class Entity
|
||||
if (!this.canPortalAsync(destination, takePassengers)) {
|
||||
return false;
|
||||
}
|
||||
+ // Luminol start - Add missing teleportation events
|
||||
+ if (!new me.earthme.luminol.api.entity.PreEntityPortalEvent(
|
||||
+ this.getBukkitEntity(),
|
||||
+ io.papermc.paper.util.MCUtil.toLocation(this.level, portalPos),
|
||||
+ destination.getWorld()
|
||||
+ ).callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
|
||||
// Kaiiju start - sync end platform spawning & entity teleportation
|
||||
final java.util.function.Consumer<Entity> tpComplete = type == PortalType.END && destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END ?
|
||||
diff --git a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
index e29e379f9b2238eafe27545681bb19c710003bcc..fdf220424f7693a7ea3ae385ddd771720825b0f7 100644
|
||||
--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
|
||||
@@ -192,6 +192,18 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity {
|
||||
portalTile.trySearchForExit(portalWorld, portalPos);
|
||||
return false;
|
||||
}
|
||||
+ // Luminol start - Add missing teleportation apis
|
||||
+ final org.bukkit.Location orginalPortalLocation = io.papermc.paper.util.MCUtil.toLocation(toTeleport.level(), portalPos);
|
||||
+ final org.bukkit.Location targetPortalLocation = io.papermc.paper.util.MCUtil.toLocation(portalWorld, teleportPos);
|
||||
+
|
||||
+ final me.earthme.luminol.api.portal.PortalLocateEvent portalLocateEvent = new me.earthme.luminol.api.portal.PortalLocateEvent(
|
||||
+ orginalPortalLocation,
|
||||
+ targetPortalLocation
|
||||
+ );
|
||||
+
|
||||
+ portalLocateEvent.callEvent();
|
||||
+ // Luminol end
|
||||
+
|
||||
|
||||
// note: we handle the position from the TeleportTransition
|
||||
net.minecraft.world.level.portal.TeleportTransition teleport = net.minecraft.world.level.block.EndGatewayBlock.getTeleportTransition(
|
||||
@@ -0,0 +1,130 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bacteriawa <A3167717663@hotmail.com>
|
||||
Date: Tue, 21 Apr 2026 02:27:38 +0800
|
||||
Subject: [PATCH] Add Portal rate limiter
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index f32d118e1e925b2155cef3fcdcb1e194c541e242..2d5d4170e1f45ae9113c37623b4066861dc79d64 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -157,6 +157,10 @@ public final class RegionizedWorldData {
|
||||
for (final ChunkHolder chunkHolder : from.chunkHoldersToBroadcast) {
|
||||
into.chunkHoldersToBroadcast.add(chunkHolder);
|
||||
}
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ into.portalRateThrottler.mergeWith(from.portalRateThrottler);
|
||||
+ from.portalRateThrottler.destroy();
|
||||
+ // Luminol end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -322,6 +326,12 @@ public final class RegionizedWorldData {
|
||||
into.chunkHoldersToBroadcast.add(chunkHolder);
|
||||
}
|
||||
}
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ for (var worldData : dataSet) {
|
||||
+ from.portalRateThrottler.splitInto(worldData.portalRateThrottler);
|
||||
+ }
|
||||
+ from.portalRateThrottler.destroy();
|
||||
+ // Luminol end
|
||||
}
|
||||
};
|
||||
|
||||
@@ -343,6 +353,35 @@ public final class RegionizedWorldData {
|
||||
return this.isHandlingTick;
|
||||
}
|
||||
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ public final me.earthme.luminol.utils.RateThrottler portalRateThrottler = new me.earthme.luminol.utils.RateThrottler();
|
||||
+ public final net.objecthunter.exp4j.Expression portalRateCapExpression = me.earthme.luminol.config.modules.function.PortalRateLimiterConfig.getExpressionIfConfigured();
|
||||
+
|
||||
+ private int computePortalRateCap() {
|
||||
+ // expression mode is disabled
|
||||
+ if (this.portalRateCapExpression == null) {
|
||||
+ return me.earthme.luminol.config.modules.function.PortalRateLimiterConfig.maxPortalTeleportsPerTick;
|
||||
+ }
|
||||
+
|
||||
+ final int tickingEntityCount = this.entityTickList.size();
|
||||
+ final int tickingChunkCount = this.tickingChunks.size();
|
||||
+ final int playerCount = this.localPlayers.size();
|
||||
+
|
||||
+ return me.earthme.luminol.config.modules.function.PortalRateLimiterConfig.computeExpression(
|
||||
+ this.portalRateCapExpression,
|
||||
+ tickingEntityCount,
|
||||
+ tickingChunkCount,
|
||||
+ playerCount
|
||||
+ );
|
||||
+ }
|
||||
+ public boolean isPortalTeleportationOutOfRate() {
|
||||
+ if (!me.earthme.luminol.config.modules.function.PortalRateLimiterConfig.enabled) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return this.portalRateThrottler.isOutOfRate(this.computePortalRateCap());
|
||||
+ }
|
||||
+ // Luminol end
|
||||
// entities
|
||||
// this is copy on write to allow packet processing to iterate safely
|
||||
private final CopyOnWriteArrayList<ServerPlayer> localPlayers = new CopyOnWriteArrayList<>();
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 350b788e17dc49118498541ad8ac54f6e0a59c9d..dc83fea1f4b8a1d2a82a52b88ee5c3157653f6f8 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1973,6 +1973,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
//net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = level.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers // Folia - region threading
|
||||
profiler.push(() -> level + " " + level.dimension().identifier());
|
||||
profiler.push("tick");
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ regionizedWorldData.portalRateThrottler.begin();
|
||||
+ // Luminol end
|
||||
|
||||
try {
|
||||
foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler
|
||||
@@ -1987,6 +1990,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
profiler.pop();
|
||||
profiler.pop();
|
||||
regionizedWorldData.explosionDensityCache.clear(); // Paper - Optimize explosions // Folia - region threading
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ regionizedWorldData.portalRateThrottler.done();
|
||||
+ // Luminol end
|
||||
}
|
||||
//this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked // Folia - region threading
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index cea4bc7036dfd8777c151a0dd811fc13579d6501..402e2f01f2b3a8e9ce5c818f07581b4dab38fc26 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1536,8 +1536,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// removed from region while ticking
|
||||
return;
|
||||
}
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ var worldData = entity.level().getCurrentWorldData();
|
||||
+ if (entity.portalProcess != null && worldData.isPortalTeleportationOutOfRate()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
if (entity.handlePortal()) {
|
||||
// portalled
|
||||
+ worldData.portalRateThrottler.increase(); // Luminol - Portal rate limiter
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1584,8 +1591,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
// removed from region while ticking
|
||||
return;
|
||||
}
|
||||
+ // Luminol start - Portal rate limiter
|
||||
+ var worldData = entity.level().getCurrentWorldData();
|
||||
+ if (entity.portalProcess != null && worldData.isPortalTeleportationOutOfRate()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
if (entity.handlePortal()) {
|
||||
// portalled
|
||||
+ worldData.portalRateThrottler.increase(); // Luminol - Portal rate limiter
|
||||
return;
|
||||
}
|
||||
// Folia end - region threading
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 22:05:23 +0800
|
||||
Subject: [PATCH] Add config for waypoint restoration
|
||||
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 0fa14f60310b063f419620539fd40898627b46b9..9800ae1d3c49800b0c7342d43d696109b5b72cf4 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -267,7 +267,7 @@ public class Commands {
|
||||
TimeCommand.register(this.dispatcher, context);
|
||||
TitleCommand.register(this.dispatcher, context);
|
||||
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
|
||||
- //WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later
|
||||
+ if (me.earthme.luminol.config.modules.experiment.CommandConfig.waypointsAndWaypointCommand) WaypointCommand.register(this.dispatcher, context); // Folia - region threading - TODO later // Luminol - Restore waypoints
|
||||
WeatherCommand.register(this.dispatcher);
|
||||
WorldBorderCommand.register(this.dispatcher);
|
||||
if (JvmProfiler.INSTANCE.isAvailable()) {
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index dc83fea1f4b8a1d2a82a52b88ee5c3157653f6f8..7840b0e00ab84eab016e971ac0c2693056fb0721 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -3117,8 +3117,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
level.players().forEach(playerx -> playerx.connection.send(packet)); // Paper - per-world game rules
|
||||
} else if (rule == GameRules.LOCATOR_BAR) {
|
||||
// this.getAllLevels().forEach(level -> { // Paper - per-world game rules
|
||||
- ServerWaypointManager waypointManager = level.getWaypointManager();
|
||||
- waypointManager.locatorBarEnabled = (Boolean) value; // Paper - optimize ServerWaypointManager with locator bar disabled
|
||||
+ ServerWaypointManager waypointManager = level.getWaypointManager(); // Luminol - Restore waypoints
|
||||
+ //waypointManager.locatorBarEnabled = (Boolean) value; // Paper - optimize ServerWaypointManager with locator bar disabled // Luminol - Restore waypoints
|
||||
if ((Boolean)value) {
|
||||
level.players().forEach(waypointManager::updatePlayer);
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 402e2f01f2b3a8e9ce5c818f07581b4dab38fc26..a1c3f3e5c7c3f32e0bdead33ebd72c7601295291 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -690,7 +690,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
|
||||
this.sleepStatus = new SleepStatus();
|
||||
this.gameEventDispatcher = new GameEventDispatcher(this);
|
||||
- this.waypointManager = new ServerWaypointManager(this); // Paper - optimize ServerWaypointManager with locator bar disabled
|
||||
+ //this.waypointManager = new ServerWaypointManager(this); // Paper - optimize ServerWaypointManager with locator bar disabled // Luminol - Restore waypoints
|
||||
+ this.waypointManager = new me.earthme.luminol.utils.FoliaServerWaypointManager(this); // Luminol - Restore waypoints
|
||||
this.environmentAttributes = EnvironmentAttributeSystem.builder().addDefaultLayers(this).build();
|
||||
//this.updateSkyBrightness(); // Folia - region threading - delay until first tick
|
||||
// Paper start - rewrite chunk system
|
||||
diff --git a/net/minecraft/world/waypoints/WaypointTransmitter.java b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||
index 2866b750a28cc32c2913d3c1afee95f05956982c..f0b62f49382eb808dcd6b6b654b99b9f7763c342 100644
|
||||
--- a/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||
+++ b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||
@@ -76,7 +76,8 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
private final LivingEntity source;
|
||||
private final Waypoint.Icon icon;
|
||||
private final ServerPlayer receiver;
|
||||
- private float lastAngle;
|
||||
+ private volatile float lastAngle; // Luminol - Restore waypoints
|
||||
+ private final java.util.UUID sourceUUID; // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
|
||||
public EntityAzimuthConnection(final LivingEntity source, final Waypoint.Icon icon, final ServerPlayer receiver) {
|
||||
this.source = source;
|
||||
@@ -84,6 +85,7 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
this.receiver = receiver;
|
||||
Vec3 direction = receiver.position().subtract(source.position()).rotateClockwise90();
|
||||
this.lastAngle = (float)Mth.atan2(direction.z(), direction.x());
|
||||
+ this.sourceUUID = this.source.getUUID(); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,16 +97,16 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointAzimuth(this.source.getUUID(), this.icon, this.lastAngle));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointAzimuth(this.sourceUUID, this.icon, this.lastAngle)); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.sourceUUID)); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void update() {
|
||||
+ public synchronized void update() { // Luminol - Restore waypoints
|
||||
Vec3 direction = this.receiver.position().subtract(this.source.position()).rotateClockwise90();
|
||||
float currentAngle = (float)Mth.atan2(direction.z(), direction.x());
|
||||
if (Mth.abs(currentAngle - this.lastAngle) > 0.008726646F) {
|
||||
@@ -118,27 +120,29 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
private final LivingEntity source;
|
||||
private final Waypoint.Icon icon;
|
||||
private final ServerPlayer receiver;
|
||||
- private BlockPos lastPosition;
|
||||
+ private volatile BlockPos lastPosition; // Luminol - Restore waypoints
|
||||
+ private final java.util.UUID sourceUUID; // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
|
||||
public EntityBlockConnection(final LivingEntity source, final Waypoint.Icon icon, final ServerPlayer receiver) {
|
||||
this.source = source;
|
||||
this.receiver = receiver;
|
||||
this.icon = icon;
|
||||
this.lastPosition = source.blockPosition();
|
||||
+ this.sourceUUID = this.source.getUUID(); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointPosition(this.source.getUUID(), this.icon, this.lastPosition));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointPosition(this.sourceUUID, this.icon, this.lastPosition)); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.sourceUUID)); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void update() {
|
||||
+ public synchronized void update() { // Luminol - Restore waypoints
|
||||
BlockPos currentPosition = this.source.blockPosition();
|
||||
if (currentPosition.distManhattan(this.lastPosition) > 0) {
|
||||
this.receiver.connection.send(ClientboundTrackedWaypointPacket.updateWaypointPosition(this.source.getUUID(), this.icon, currentPosition));
|
||||
@@ -161,13 +165,15 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
private final LivingEntity source;
|
||||
private final Waypoint.Icon icon;
|
||||
private final ServerPlayer receiver;
|
||||
- private ChunkPos lastPosition;
|
||||
+ private volatile ChunkPos lastPosition; // Luminol - Restore waypoints
|
||||
+ private final java.util.UUID sourceUUID; // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
|
||||
public EntityChunkConnection(final LivingEntity source, final Waypoint.Icon icon, final ServerPlayer receiver) {
|
||||
this.source = source;
|
||||
this.icon = icon;
|
||||
this.receiver = receiver;
|
||||
this.lastPosition = source.chunkPosition();
|
||||
+ this.sourceUUID = this.source.getUUID(); // Luminol - Restore waypoints (prevent UUID mutation)
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,16 +183,16 @@ public interface WaypointTransmitter extends Waypoint {
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointChunk(this.source.getUUID(), this.icon, this.lastPosition));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.addWaypointChunk(this.sourceUUID, this.icon, this.lastPosition)); // Luminol - Restore waypoints (prevent UUID mutable)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
- this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.source.getUUID()));
|
||||
+ this.receiver.connection.send(ClientboundTrackedWaypointPacket.removeWaypoint(this.sourceUUID)); // Luminol - Restore waypoints (prevent UUID mutable)
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void update() {
|
||||
+ public synchronized void update() { // Luminol - Restore waypoints
|
||||
ChunkPos currentPosition = this.source.chunkPosition();
|
||||
if (currentPosition.getChessboardDistance(this.lastPosition) > 0) {
|
||||
this.receiver.connection.send(ClientboundTrackedWaypointPacket.updateWaypointChunk(this.source.getUUID(), this.icon, currentPosition));
|
||||
+423
@@ -0,0 +1,423 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:39:22 +0800
|
||||
Subject: [PATCH] Leaf: Secure seed and matter seed command
|
||||
|
||||
Co-authored by: Apehum <apehumchik@gmail.com>
|
||||
As part of: Leaf (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/leaf-server/paper-patches/features/0019-Matter-Secure-Seed.patch and https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/leaf-server/minecraft-patches/features/0050-Matter-Secure-Seed-command.patch)
|
||||
Licensed under: GPL-3.0 (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/licenses/GPL-3.0.txt)
|
||||
|
||||
diff --git a/net/minecraft/server/commands/SeedCommand.java b/net/minecraft/server/commands/SeedCommand.java
|
||||
index 86ee3b3ae028597576b9549bc4954dfcbaa6732c..2042dc0c7046dec25ff46ddd1e5bd45c3358040b 100644
|
||||
--- a/net/minecraft/server/commands/SeedCommand.java
|
||||
+++ b/net/minecraft/server/commands/SeedCommand.java
|
||||
@@ -13,6 +13,15 @@ public class SeedCommand {
|
||||
long seed = c.getSource().getLevel().getSeed();
|
||||
Component seedText = ComponentUtils.copyOnClickText(String.valueOf(seed));
|
||||
c.getSource().sendSuccess(() -> Component.translatable("commands.seed.success", seedText), false);
|
||||
+ // Leaf start - Matter - SecureSeed Command
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ su.plo.matter.Globals.setupGlobals(c.getSource().getLevel());
|
||||
+ String seedStr = su.plo.matter.Globals.seedToString(su.plo.matter.Globals.worldSeed);
|
||||
+ Component featureSeedComponent = ComponentUtils.copyOnClickText(seedStr);
|
||||
+
|
||||
+ c.getSource().sendSuccess(() -> Component.translatable(("Feature seed: %s"), featureSeedComponent), false);
|
||||
+ }
|
||||
+ // Leaf end - Matter - SecureSeed Command
|
||||
return (int)seed;
|
||||
})
|
||||
);
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServerProperties.java b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
index 639a5400499266f83cf8b7c1251483cd8fb699a4..8c0bee7856c8ac62880038770c2f430ecd6c44d9 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
@@ -139,7 +139,17 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
|
||||
String levelSeed = this.get("level-seed", "");
|
||||
boolean generateStructures = this.get("generate-structures", true);
|
||||
long seed = WorldOptions.parseSeed(levelSeed).orElse(WorldOptions.randomSeed());
|
||||
- this.worldOptions = new WorldOptions(seed, generateStructures, false);
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ String featureSeedStr = this.get("feature-level-seed", "");
|
||||
+ long[] featureSeed = su.plo.matter.Globals.parseSeed(featureSeedStr)
|
||||
+ .orElse(su.plo.matter.Globals.createRandomWorldSeed());
|
||||
+
|
||||
+ this.worldOptions = new WorldOptions(seed, featureSeed, generateStructures, false);
|
||||
+ } else {
|
||||
+ this.worldOptions = new WorldOptions(seed, generateStructures, false);
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
this.worldDimensionData = new DedicatedServerProperties.WorldDimensionData(
|
||||
this.get("generator-settings", s -> GsonHelper.parse(!s.isEmpty() ? s : "{}"), new JsonObject()),
|
||||
this.get("level-type", v -> v.toLowerCase(Locale.ROOT), WorldPresets.NORMAL.identifier().toString())
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 7927769cf9bccb892745f4d1390eb83b2861d1bb..414c21345879f589fb61130180d0ca606e37a454 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -671,6 +671,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
|
||||
public ChunkGenerator getGenerator() {
|
||||
+ su.plo.matter.Globals.setupGlobals(level); // Leaf - Matter - Secure Seed
|
||||
return this.chunkMap.generator();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index a1c3f3e5c7c3f32e0bdead33ebd72c7601295291..85eed61919b3c2ef93943e1c1b50fbcbca6fb319 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -639,6 +639,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
generator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, generator, gen);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ su.plo.matter.Globals.setupGlobals(this); // Leaf - Matter - Secure Seed
|
||||
boolean syncWrites = server.forceSynchronousWrites();
|
||||
DataFixer fixerUpper = server.getFixerUpper();
|
||||
// Paper - rewrite chunk system
|
||||
diff --git a/net/minecraft/world/entity/monster/cubemob/Slime.java b/net/minecraft/world/entity/monster/cubemob/Slime.java
|
||||
index 984ec15bdebcb541cd6ee9014a654ea58988f6f1..da3bbf395ef5c173124fc564d0d7d9c96346436e 100644
|
||||
--- a/net/minecraft/world/entity/monster/cubemob/Slime.java
|
||||
+++ b/net/minecraft/world/entity/monster/cubemob/Slime.java
|
||||
@@ -94,7 +94,12 @@ public class Slime extends AbstractCubeMob implements Enemy {
|
||||
}
|
||||
|
||||
ChunkPos chunkPos = ChunkPos.containing(pos);
|
||||
- boolean slimeChunk = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkPos.x(), chunkPos.z(), worldGenLevel.getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ boolean isSlimeChunk = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled
|
||||
+ ? level.getChunk(chunkPos.x(), chunkPos.z()).isSlimeChunk()
|
||||
+ : WorldgenRandom.seedSlimeChunk(chunkPos.x(), chunkPos.z(), worldGenLevel.getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
|
||||
+ boolean slimeChunk = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
// Paper start - Replace rules for Height in Slime Chunks
|
||||
final double maxHeightSlimeChunk = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
|
||||
if (random.nextInt(10) == 0 && slimeChunk && pos.getY() < maxHeightSlimeChunk) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
index 28f703204afd834cd50335346ef065670d6b37ad..f6cecf0ec1ebf9dd7028877dcadf191d1a2d954c 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -83,6 +83,10 @@ public abstract class ChunkAccess implements LightChunk, StructureAccess, BiomeM
|
||||
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(ChunkAccess.DATA_TYPE_REGISTRY);
|
||||
// CraftBukkit end
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ private boolean slimeChunk;
|
||||
+ private boolean hasComputedSlimeChunk;
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
|
||||
// Paper start - rewrite chunk system
|
||||
private volatile ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles;
|
||||
@@ -186,6 +190,17 @@ public abstract class ChunkAccess implements LightChunk, StructureAccess, BiomeM
|
||||
return GameEventListenerRegistry.NOOP;
|
||||
}
|
||||
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ public boolean isSlimeChunk() {
|
||||
+ if (!hasComputedSlimeChunk) {
|
||||
+ hasComputedSlimeChunk = true;
|
||||
+ slimeChunk = su.plo.matter.WorldgenCryptoRandom.seedSlimeChunk(chunkPos.x(), chunkPos.z()).nextInt(10) == 0;
|
||||
+ }
|
||||
+
|
||||
+ return slimeChunk;
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+
|
||||
public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
|
||||
|
||||
public @Nullable BlockState setBlockState(final BlockPos pos, final BlockState state) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index b7325170369299a74be35ecc66a6446c301605b8..bac2047025bf133d14438b5f667bb12401b5cdca 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -347,7 +347,11 @@ public abstract class ChunkGenerator {
|
||||
Map<Integer, List<Structure>> structuresByStep = structuresRegistry.stream()
|
||||
.collect(Collectors.groupingBy(structure -> structure.step().ordinal()));
|
||||
List<FeatureSorter.StepFeatureData> featureList = this.featuresPerStep.get();
|
||||
- WorldgenRandom random = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(origin.getX(), origin.getZ(), su.plo.matter.Globals.Salt.UNDEFINED, 0)
|
||||
+ : new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
long decorationSeed = random.setDecorationSeed(level.getSeed(), origin.getX(), origin.getZ());
|
||||
Set<Holder<Biome>> possibleBiomes = new ObjectArraySet<>();
|
||||
ChunkPos.rangeClosed(sectionPos.chunk(), 1).forEach(chunkPos -> {
|
||||
@@ -571,8 +575,15 @@ public abstract class ChunkGenerator {
|
||||
} else {
|
||||
ArrayList<StructureSet.StructureSelectionEntry> options = new ArrayList<>(structures.size());
|
||||
options.addAll(structures);
|
||||
- WorldgenRandom random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- random.setLargeFeatureSeed(state.getLevelSeed(), sourceChunkPos.x(), sourceChunkPos.z());
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random;
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ random = new su.plo.matter.WorldgenCryptoRandom(sourceChunkPos.x(), sourceChunkPos.z(), su.plo.matter.Globals.Salt.GENERATE_FEATURE, 0);
|
||||
+ } else {
|
||||
+ random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ random.setLargeFeatureSeed(state.getLevelSeed(), sourceChunkPos.x(), sourceChunkPos.z());
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
int total = 0;
|
||||
|
||||
for (StructureSet.StructureSelectionEntry option : options) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
index 8b4ea2b16da45bcefe743990866e43c94e121825..9d91679a2696c065cd99cd6ce395c0d00c9dd933 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
@@ -203,14 +203,20 @@ public class ChunkGeneratorStructureState {
|
||||
List<CompletableFuture<ChunkPos>> tasks = new ArrayList<>(count);
|
||||
int spread = placement.spread();
|
||||
HolderSet<Biome> preferredBiomes = placement.preferredBiomes();
|
||||
- RandomSource random = RandomSource.create();
|
||||
- // Paper start - Add missing structure set seed configs
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ RandomSource random = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.STRONGHOLDS, 0)
|
||||
+ :RandomSource.create();
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+ if (!me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ //Paper start - Add missing structure set seed configs
|
||||
if (this.conf.strongholdSeed != null && structureSet.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
|
||||
random.setSeed(this.conf.strongholdSeed);
|
||||
} else {
|
||||
// Paper end - Add missing structure set seed configs
|
||||
random.setSeed(this.concentricRingsSeed);
|
||||
} // Paper - Add missing structure set seed configs
|
||||
+ } // Leaf - Matter - Secure Seed
|
||||
double angle = random.nextDouble() * Math.PI * 2.0;
|
||||
int positionInCircle = 0;
|
||||
int circle = 0;
|
||||
diff --git a/net/minecraft/world/level/chunk/status/ChunkStep.java b/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
index 9208924f54d5024bc50ad4501fbff9eb2a289181..01d87d9c474a5f3e14713579e6a1d1e17d2455ae 100644
|
||||
--- a/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
+++ b/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
@@ -60,6 +60,7 @@ public final class ChunkStep implements ca.spottedleaf.moonrise.patches.chunk_sy
|
||||
}
|
||||
|
||||
public CompletableFuture<ChunkAccess> apply(final WorldGenContext context, final StaticCache2D<GenerationChunkHolder> cache, final ChunkAccess chunk) {
|
||||
+ su.plo.matter.Globals.setupGlobals(context.level()); // Leaf - Matter - Secure Seed
|
||||
if (chunk.getPersistedStatus().isBefore(this.targetStatus)) {
|
||||
ProfiledDuration profiledDuration = JvmProfiler.INSTANCE.onChunkGenerate(chunk.getPos(), context.level().dimension(), this.targetStatus.getName());
|
||||
return this.task.doWork(context, this, cache, chunk).thenApply(newCenterChunk -> this.completeChunkGeneration(newCenterChunk, profiledDuration));
|
||||
diff --git a/net/minecraft/world/level/levelgen/WorldOptions.java b/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
index 4ad94af024d81b7dfe910dcee2a6ec7a9b200d56..38495536001442b1591251d7625ccdad4b73caf3 100644
|
||||
--- a/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
+++ b/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
@@ -10,8 +10,22 @@ import net.minecraft.util.RandomSource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class WorldOptions {
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ private static final com.google.gson.Gson gson = new com.google.gson.Gson();
|
||||
+ private static final boolean isSecureSeedEnabled = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled;
|
||||
public static final MapCodec<WorldOptions> CODEC = RecordCodecBuilder.mapCodec(
|
||||
- i -> i.group(
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ i -> isSecureSeedEnabled
|
||||
+ ? i.group(
|
||||
+ Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
|
||||
+ Codec.STRING.fieldOf("feature_seed").orElse(gson.toJson(su.plo.matter.Globals.createRandomWorldSeed())).stable().forGetter(WorldOptions::featureSeedSerialize),
|
||||
+ Codec.BOOL.fieldOf("generate_features").orElse(true).stable().forGetter(WorldOptions::generateStructures),
|
||||
+ Codec.BOOL.fieldOf("bonus_chest").orElse(false).stable().forGetter(WorldOptions::generateBonusChest),
|
||||
+ Codec.STRING.lenientOptionalFieldOf("legacy_custom_options").stable().forGetter(worldOptions -> worldOptions.legacyCustomOptions)
|
||||
+ )
|
||||
+ .apply(i, i.stable(WorldOptions::new))
|
||||
+ : i.group(
|
||||
+ // Leaf end
|
||||
Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
|
||||
ExtraCodecs.optionalAlwaysPresentFieldOf(Codec.BOOL, "generate_structures", true).stable().forGetter(WorldOptions::generateStructures),
|
||||
ExtraCodecs.optionalAlwaysPresentFieldOf(Codec.BOOL, "bonus_chest", false).stable().forGetter(WorldOptions::generateBonusChest),
|
||||
@@ -19,8 +33,14 @@ public class WorldOptions {
|
||||
)
|
||||
.apply(i, i.stable(WorldOptions::new))
|
||||
);
|
||||
- public static final WorldOptions DEMO_OPTIONS = new WorldOptions("North Carolina".hashCode(), true, true);
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ public static final WorldOptions DEMO_OPTIONS = isSecureSeedEnabled
|
||||
+ ? new WorldOptions((long) "North Carolina".hashCode(), su.plo.matter.Globals.createRandomWorldSeed(), true, true)
|
||||
+ : new WorldOptions("North Carolina".hashCode(), true, true);
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
private final long seed;
|
||||
+ private long[] featureSeed = su.plo.matter.Globals.createRandomWorldSeed(); // Leaf - Matter - Secure Seed
|
||||
private final boolean generateStructures;
|
||||
private final boolean generateBonusChest;
|
||||
private final Optional<String> legacyCustomOptions;
|
||||
@@ -29,14 +49,35 @@ public class WorldOptions {
|
||||
this(seed, generateStructures, generateBonusChest, Optional.empty());
|
||||
}
|
||||
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ public WorldOptions(long seed, long[] featureSeed, boolean generateStructures, boolean bonusChest) {
|
||||
+ this(seed, featureSeed, generateStructures, bonusChest, Optional.empty());
|
||||
+ }
|
||||
+
|
||||
+ private WorldOptions(long seed, String featureSeedJson, boolean generateStructures, boolean bonusChest, Optional<String> legacyCustomOptions) {
|
||||
+ this(seed, gson.fromJson(featureSeedJson, long[].class), generateStructures, bonusChest, legacyCustomOptions);
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+
|
||||
public static WorldOptions defaultWithRandomSeed() {
|
||||
- return new WorldOptions(randomSeed(), true, false);
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(randomSeed(), su.plo.matter.Globals.createRandomWorldSeed(), true, false)
|
||||
+ : new WorldOptions(randomSeed(), true, false);
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
}
|
||||
|
||||
public static WorldOptions testWorldWithRandomSeed() {
|
||||
return new WorldOptions(randomSeed(), false, false);
|
||||
}
|
||||
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ private WorldOptions(long seed, long[] featureSeed, boolean generateStructures, boolean bonusChest, Optional<String> legacyCustomOptions) {
|
||||
+ this(seed, generateStructures, bonusChest, legacyCustomOptions);
|
||||
+ this.featureSeed = featureSeed;
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+
|
||||
private WorldOptions(final long seed, final boolean generateStructures, final boolean generateBonusChest, final Optional<String> legacyCustomOptions) {
|
||||
this.seed = seed;
|
||||
this.generateStructures = generateStructures;
|
||||
@@ -48,6 +89,16 @@ public class WorldOptions {
|
||||
return this.seed;
|
||||
}
|
||||
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ public long[] featureSeed() {
|
||||
+ return this.featureSeed;
|
||||
+ }
|
||||
+
|
||||
+ private String featureSeedSerialize() {
|
||||
+ return gson.toJson(this.featureSeed);
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+
|
||||
public boolean generateStructures() {
|
||||
return this.generateStructures;
|
||||
}
|
||||
@@ -60,17 +111,25 @@ public class WorldOptions {
|
||||
return this.legacyCustomOptions.isPresent();
|
||||
}
|
||||
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
public WorldOptions withBonusChest(final boolean generateBonusChest) {
|
||||
- return new WorldOptions(this.seed, this.generateStructures, generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(this.seed, this.featureSeed, this.generateStructures, generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(this.seed, this.generateStructures, generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
|
||||
public WorldOptions withStructures(final boolean generateStructures) {
|
||||
- return new WorldOptions(this.seed, generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(this.seed, this.featureSeed, generateStructures, this.generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(this.seed, generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
|
||||
public WorldOptions withSeed(final OptionalLong seed) {
|
||||
- return new WorldOptions(seed.orElse(randomSeed()), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(seed.orElse(randomSeed()), su.plo.matter.Globals.createRandomWorldSeed(), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(seed.orElse(randomSeed()), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
|
||||
public static OptionalLong parseSeed(String seedString) {
|
||||
seedString = seedString.trim();
|
||||
diff --git a/net/minecraft/world/level/levelgen/feature/GeodeFeature.java b/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
index baed0479a4552676844989868ee4c37ffa344def..55abc8e32d9dabbb5699d6eff109f4067c452098 100644
|
||||
--- a/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
+++ b/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
@@ -43,7 +43,11 @@ public class GeodeFeature extends Feature<GeodeConfiguration> {
|
||||
int maxGenOffset = config.maxGenOffset();
|
||||
List<Pair<BlockPos, Integer>> points = Lists.newLinkedList();
|
||||
int numPoints = config.distributionPoints().sample(random);
|
||||
- WorldgenRandom random1 = new WorldgenRandom(new LegacyRandomSource(level.getSeed()));
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random1 = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.GEODE_FEATURE, 0)
|
||||
+ : new WorldgenRandom(new LegacyRandomSource(level.getSeed()));
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
NormalNoise noise = NormalNoise.create(random1, -4, 1.0);
|
||||
List<BlockPos> crackPoints = Lists.newLinkedList();
|
||||
double crackSizeAdjustment = (double)numPoints / config.outerWallDistance().maxInclusive();
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/Structure.java b/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
index f1e13ede1f7345089ece8d8ef391f7fd5e55c445..a3a1ab1b610fd0f75c4d5cc96ab921e47d0cfea7 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
@@ -248,6 +248,11 @@ public abstract class Structure {
|
||||
}
|
||||
|
||||
private static WorldgenRandom makeRandom(final long seed, final ChunkPos chunkPos) {
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ return new su.plo.matter.WorldgenCryptoRandom(chunkPos.x(), chunkPos.z(), su.plo.matter.Globals.Salt.GENERATE_FEATURE, seed);
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
WorldgenRandom random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
random.setLargeFeatureSeed(seed, chunkPos.x(), chunkPos.z());
|
||||
return random;
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java b/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
index 1310b2ca994b8f6d3d92bdc676fe44de3619cc09..8fcb08d7ffc90d2d46375faecd17774483a4560a 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
@@ -67,8 +67,15 @@ public class RandomSpreadStructurePlacement extends StructurePlacement {
|
||||
public ChunkPos getPotentialStructureChunk(final long seed, final int sourceX, final int sourceZ) {
|
||||
int spacedGridX = Math.floorDiv(sourceX, this.spacing);
|
||||
int spacedGridZ = Math.floorDiv(sourceZ, this.spacing);
|
||||
- WorldgenRandom random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- random.setLargeFeatureWithSalt(seed, spacedGridX, spacedGridZ, this.salt());
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random;
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ random = new su.plo.matter.WorldgenCryptoRandom(spacedGridX, spacedGridZ, su.plo.matter.Globals.Salt.POTENTIONAL_FEATURE, this.salt);
|
||||
+ } else {
|
||||
+ random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ random.setLargeFeatureWithSalt(seed, spacedGridX, spacedGridZ, this.salt());
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
int limit = this.spacing - this.separation;
|
||||
int spreadX = this.spreadType.evaluate(random, limit);
|
||||
int spreadZ = this.spreadType.evaluate(random, limit);
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
index 646df0237a5a2863f75e6c5f9dfe9ddf512c540f..1a5690b793ad6c30690fc9659c7f1746c55e5997 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
@@ -137,8 +137,16 @@ public abstract class StructurePlacement {
|
||||
}
|
||||
|
||||
private static boolean legacyArbitrarySaltProbabilityReducer(final long seed, final int salt, final int sourceX, final int sourceZ, final float probability, final @org.jspecify.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs
|
||||
- WorldgenRandom random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- random.setLargeFeatureWithSalt(seed, sourceX, sourceZ, saltOverride != null ? saltOverride : HIGHLY_ARBITRARY_RANDOM_SALT); // Paper - Add missing structure set seed configs
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random;
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled) {
|
||||
+ random = new su.plo.matter.WorldgenCryptoRandom(sourceX, sourceZ, su.plo.matter.Globals.Salt.UNDEFINED, saltOverride != null ? saltOverride : HIGHLY_ARBITRARY_RANDOM_SALT);
|
||||
+ } else {
|
||||
+ random = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ random.setLargeFeatureWithSalt(seed, sourceX, sourceZ, saltOverride != null ? saltOverride : HIGHLY_ARBITRARY_RANDOM_SALT); // Paper - Add missing structure set seed configs
|
||||
+ }
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
+
|
||||
return random.nextFloat() < probability;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
index b92da7acae0789d955a9f71072b95ed030b879e2..484977ebf2cd7b75b228ebd7246fe602c2a271d1 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
@@ -64,7 +64,11 @@ public class JigsawPlacement {
|
||||
ChunkGenerator chunkGenerator = context.chunkGenerator();
|
||||
StructureTemplateManager structureTemplateManager = context.structureTemplateManager();
|
||||
LevelHeightAccessor heightAccessor = context.heightAccessor();
|
||||
- WorldgenRandom random = context.random();
|
||||
+ // Leaf start - Matter - Secure Seed
|
||||
+ WorldgenRandom random = me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(context.chunkPos().x(), context.chunkPos().z(), su.plo.matter.Globals.Salt.JIGSAW_PLACEMENT, 0)
|
||||
+ : context.random();
|
||||
+ // Leaf end - Matter - Secure Seed
|
||||
Registry<StructureTemplatePool> pools = registryAccess.lookupOrThrow(Registries.TEMPLATE_POOL);
|
||||
Rotation centerRotation = Rotation.getRandom(random);
|
||||
StructureTemplatePool centerPool = startPool.unwrapKey()
|
||||
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Libalpm64 <libalpm@proton.me>
|
||||
Date: Mon, 2 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] Add secure seed V2 with Blake3
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/RandomState.java b/net/minecraft/world/level/levelgen/RandomState.java
|
||||
index 7b74440fbbe79c018ad59d24b99da0c6d4a9d007..208d4b93ee47083bd9069aec710c6db27044203c 100644
|
||||
--- a/net/minecraft/world/level/levelgen/RandomState.java
|
||||
+++ b/net/minecraft/world/level/levelgen/RandomState.java
|
||||
@@ -33,10 +33,28 @@ public final class RandomState {
|
||||
}
|
||||
|
||||
private RandomState(final NoiseGeneratorSettings settings, final HolderGetter<NormalNoise.NoiseParameters> noises, final long seed) {
|
||||
- this.random = settings.getRandomSource().newInstance(seed).forkPositional();
|
||||
+ // this.random = settings.getRandomSource().newInstance(seed).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
+ // Luminol start - Add secure seed V2 with Blake3
|
||||
+ final long[] secureWorldSeed = (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2)
|
||||
+ ? su.plo.matter.HashingV2.expandLevelSeedTo1024Bits(seed)
|
||||
+ : null;
|
||||
+
|
||||
+ long terrainSeed = (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2)
|
||||
+ ? su.plo.matter.HashingV2.getTerrainSeed(secureWorldSeed, su.plo.matter.HashingV2.TerrainType.BASE_TERRAIN)
|
||||
+ : seed;
|
||||
+ long aquiferSeed = (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2)
|
||||
+ ? su.plo.matter.HashingV2.getTerrainSeed(secureWorldSeed, su.plo.matter.HashingV2.TerrainType.AQUIFER)
|
||||
+ : seed;
|
||||
+ long oreSeed = (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2)
|
||||
+ ? su.plo.matter.HashingV2.getTerrainSeed(secureWorldSeed, su.plo.matter.HashingV2.TerrainType.ORE)
|
||||
+ : seed;
|
||||
+ // Luminol end
|
||||
+ this.random = settings.getRandomSource().newInstance(terrainSeed).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
this.noises = noises;
|
||||
- this.aquiferRandom = this.random.fromHashOf(Identifier.withDefaultNamespace("aquifer")).forkPositional();
|
||||
- this.oreRandom = this.random.fromHashOf(Identifier.withDefaultNamespace("ore")).forkPositional();
|
||||
+ //this.aquiferRandom = this.random.fromHashOf(Identifier.withDefaultNamespace("aquifer")).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
+ //this.oreRandom = this.random.fromHashOf(Identifier.withDefaultNamespace("ore")).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
+ this.aquiferRandom = settings.getRandomSource().newInstance(aquiferSeed).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
+ this.oreRandom = settings.getRandomSource().newInstance(oreSeed).forkPositional(); // Luminol - Add secure seed V2 with Blake3
|
||||
this.noiseIntances = new ConcurrentHashMap<>();
|
||||
this.positionalRandoms = new ConcurrentHashMap<>();
|
||||
this.surfaceSystem = new SurfaceSystem(this, settings.defaultBlock(), settings.seaLevel(), this.random);
|
||||
@@ -46,6 +64,12 @@ public final class RandomState {
|
||||
private final Map<DensityFunction, DensityFunction> wrapped = new HashMap<>();
|
||||
|
||||
private RandomSource newLegacyInstance(final long seedOffset) {
|
||||
+ // Luminol start - Add secure seed V2 with Blake3
|
||||
+ if (me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2) {
|
||||
+ long climateSeed = su.plo.matter.HashingV2.getTerrainSeed(secureWorldSeed, su.plo.matter.HashingV2.TerrainType.CLIMATE);
|
||||
+ return new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.UNDEFINED, climateSeed + seed);
|
||||
+ }
|
||||
+ // Luminol end
|
||||
return new LegacyRandomSource(seed + seedOffset);
|
||||
}
|
||||
|
||||
@@ -71,7 +95,13 @@ public final class RandomState {
|
||||
: RandomState.this.random.fromHashOf(Identifier.withDefaultNamespace("terrain"));
|
||||
return noise.withNewRandom(terrainRandom);
|
||||
} else {
|
||||
- return function instanceof DensityFunctions.EndIslandDensityFunction ? new DensityFunctions.EndIslandDensityFunction(seed) : function;
|
||||
+ return function instanceof DensityFunctions.EndIslandDensityFunction //? new DensityFunctions.EndIslandDensityFunction(seed)// Luminol - Add secure seed V2 with Blake3
|
||||
+ // Luminol start - Add secure seed V2 with Blake3
|
||||
+ ? new DensityFunctions.EndIslandDensityFunction((me.earthme.luminol.config.modules.function.SecureSeedConfig.enabled && me.earthme.luminol.config.modules.function.SecureSeedConfig.version == 2)
|
||||
+ ? su.plo.matter.HashingV2.getTerrainSeed(secureWorldSeed, su.plo.matter.HashingV2.TerrainType.SURFACE)
|
||||
+ : seed)
|
||||
+ // Luminol end
|
||||
+ : function;
|
||||
}
|
||||
}
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:27:21 +0800
|
||||
Subject: [PATCH] Leaf: Replace brain maps with optimized collection
|
||||
|
||||
Co-authored by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
As part of: Leaf (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/leaf-server/minecraft-patches/features/0070-Replace-brain-maps-with-optimized-collection.patch)
|
||||
Licensed under: MIT (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/licenses/MIT.txt)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
|
||||
index 27894e2935e2afee8190708def4be3b00f922f64..71a11238835b1090c283d03cc30e09b8a65a9762 100644
|
||||
--- a/net/minecraft/world/entity/ai/Brain.java
|
||||
+++ b/net/minecraft/world/entity/ai/Brain.java
|
||||
@@ -37,14 +37,14 @@ import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class Brain<E extends LivingEntity> {
|
||||
private static final int SCHEDULE_UPDATE_DELAY = 20;
|
||||
- private final Map<MemoryModuleType<?>, MemorySlot<?>> memories = Maps.newHashMap();
|
||||
- private final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap();
|
||||
+ private final Map<MemoryModuleType<?>, MemorySlot<?>> memories = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Leaf - Replace brain maps with optimized collection
|
||||
+ private final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Leaf - Replace brain maps with optimized collection
|
||||
private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap();
|
||||
private @Nullable EnvironmentAttribute<Activity> schedule;
|
||||
- private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
|
||||
- private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap();
|
||||
- private Set<Activity> coreActivities = Sets.newHashSet();
|
||||
- private final Set<Activity> activeActivities = Sets.newHashSet();
|
||||
+ private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Leaf - Replace brain maps with optimized collection
|
||||
+ private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Leaf - Replace brain maps with optimized collection
|
||||
+ private Set<Activity> coreActivities = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(); // Leaf - Replace brain maps with optimized collection
|
||||
+ private final Set<Activity> activeActivities = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(); // Leaf - Replace brain maps with optimized collection
|
||||
private Activity defaultActivity = Activity.IDLE;
|
||||
private long lastScheduleUpdate = -9999L;
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:51:53 +0800
|
||||
Subject: [PATCH] Leaf: Remove useless creating stats json bases on player name
|
||||
logic
|
||||
|
||||
Co-authored by: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
|
||||
As part of: Leaf (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/leaf-server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch)
|
||||
Licensed under: MIT (https://github.com/Winds-Studio/Leaf/blob/7f3e240bbe0970683c40279a7a65f0fde47503b6/licenses/MIT.txt)
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 53449af103c1774f68cb0c296d47e7032e4e3843..a8f051e6aff31a723a3ba59842fac3a43f4911fe 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1294,22 +1294,26 @@ public abstract class PlayerList {
|
||||
Path uuidStatsFile = statFolder.resolve(gameProfile.id() + ".json");
|
||||
if (Files.exists(uuidStatsFile)) {
|
||||
return uuidStatsFile;
|
||||
- }
|
||||
-
|
||||
- String playerNameStatsFile = gameProfile.name() + ".json";
|
||||
- if (FileUtil.isValidPathSegment(playerNameStatsFile)) {
|
||||
- Path playerNameStatsPath = statFolder.resolve(playerNameStatsFile);
|
||||
- if (Files.isRegularFile(playerNameStatsPath)) {
|
||||
- try {
|
||||
- return Files.move(playerNameStatsPath, uuidStatsFile);
|
||||
- } catch (IOException e) {
|
||||
- LOGGER.warn("Failed to copy file {} to {}", playerNameStatsFile, uuidStatsFile);
|
||||
- return playerNameStatsPath;
|
||||
+ } else {
|
||||
+ // Leaf start - Remove useless creating stats json bases on player name logic
|
||||
+ /*
|
||||
+ String playerNameStatsFile = gameProfile.name() + ".json";
|
||||
+ if (FileUtil.isValidPathSegment(playerNameStatsFile)) {
|
||||
+ Path playerNameStatsPath = statFolder.resolve(playerNameStatsFile);
|
||||
+ if (Files.isRegularFile(playerNameStatsPath)) {
|
||||
+ try {
|
||||
+ return Files.move(playerNameStatsPath, uuidStatsFile);
|
||||
+ } catch (IOException e) {
|
||||
+ LOGGER.warn("Failed to copy file {} to {}", playerNameStatsFile, uuidStatsFile);
|
||||
+ return playerNameStatsPath;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- }
|
||||
+ */
|
||||
+ // Leaf end - Remove useless creating stats json bases on player name logic
|
||||
|
||||
- return uuidStatsFile;
|
||||
+ return uuidStatsFile;
|
||||
+ }
|
||||
}
|
||||
|
||||
public PlayerAdvancements getPlayerAdvancements(final ServerPlayer player) {
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 2 May 2026 22:26:57 +0800
|
||||
Subject: [PATCH] Leaf Optimize PatchedDataComponentMap equals
|
||||
|
||||
This is a part of Leaf(https://github.com/Winds-Studio/Leaf/blob/db41340915c7768d726342fb29d16bc428081074/leaf-server/minecraft-patches/features/0300-Optimize-PatchedDataComponentMap-equals.patch)
|
||||
|
||||
Original author: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
|
||||
|
||||
Original license: https://github.com/Winds-Studio/Leaf/blob/db41340915c7768d726342fb29d16bc428081074/LICENSE.md
|
||||
|
||||
diff --git a/net/minecraft/core/component/PatchedDataComponentMap.java b/net/minecraft/core/component/PatchedDataComponentMap.java
|
||||
index 08ea8107fc8cbec3742278ab5cf03ef9048720f9..217e4fb33d2707c5e50c7ec2dd2aaee410154254 100644
|
||||
--- a/net/minecraft/core/component/PatchedDataComponentMap.java
|
||||
+++ b/net/minecraft/core/component/PatchedDataComponentMap.java
|
||||
@@ -221,7 +221,19 @@ public final class PatchedDataComponentMap implements DataComponentMap {
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
- return this == obj || obj instanceof PatchedDataComponentMap otherMap && this.prototype.equals(otherMap.prototype) && this.patch.equals(otherMap.patch);
|
||||
+ // return this == obj || obj instanceof PatchedDataComponentMap otherMap && this.prototype.equals(otherMap.prototype) && this.patch.equals(otherMap.patch); // Leaf - Optimize PatchedDataComponentMap equals
|
||||
+ // Leaf start - Optimize PatchedDataComponentMap equals
|
||||
+ if (this == obj) return true;
|
||||
+ if (!(obj instanceof PatchedDataComponentMap that)) return false;
|
||||
+ if (this.patch.size() != that.patch.size()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!this.prototype.equals(that.prototype)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (this.patch == that.patch) return true;
|
||||
+ return this.patch.equals(that.patch);
|
||||
+ // Leaf end - Optimize PatchedDataComponentMap equals
|
||||
}
|
||||
|
||||
@Override
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Mon, 4 May 2026 13:44:05 +0800
|
||||
Subject: [PATCH] Leaf Better checking for useless move packets
|
||||
|
||||
A part of leaf(https://github.com/Winds-Studio/Leaf/blob/b794fca6080c47ff305b6d065a579171b1fe1e98/leaf-server/minecraft-patches/features/0018-Better-checking-for-useless-move-packets.patch)
|
||||
|
||||
Original license: https://github.com/Winds-Studio/Leaf/blob/b794fca6080c47ff305b6d065a579171b1fe1e98/LICENSE.md
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||
index 60af82925d2f7e605bf7340cf01f1a5668f4d725..2e71a1cbabf3405e3e4fd5349a1784d895e7e60c 100644
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -186,18 +186,35 @@ public class ServerEntity {
|
||||
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
|
||||
sentPosition = true;
|
||||
sentRotation = true;
|
||||
- } else if ((!pos || !shouldSendRotation) && !(this.entity instanceof AbstractArrow)) {
|
||||
+ /*} else if ((!pos || !shouldSendRotation) && !(this.entity instanceof AbstractArrow)) { // Gale - Airplane - better checking for useless move packets
|
||||
if (pos) {
|
||||
packet = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short)xa, (short)ya, (short)za, this.entity.onGround());
|
||||
sentPosition = true;
|
||||
} else if (shouldSendRotation) {
|
||||
packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), yRotn, xRotn, this.entity.onGround());
|
||||
sentRotation = true;
|
||||
- }
|
||||
+ }*/ // Gale - Airplane - better checking for useless move packets
|
||||
} else {
|
||||
- packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)xa, (short)ya, (short)za, yRotn, xRotn, this.entity.onGround());
|
||||
+ /*packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)xa, (short)ya, (short)za, yRotn, xRotn, this.entity.onGround()); // Gale - Airplane - better checking for useless move packets
|
||||
sentPosition = true;
|
||||
- sentRotation = true;
|
||||
+ sentRotation = true;*/ // Gale - Airplane - better checking for useless move packets
|
||||
+ // Gale start - Airplane - better checking for useless move packets
|
||||
+ if (pos || shouldSendRotation || this.entity instanceof AbstractArrow) {
|
||||
+ if ((!pos || !shouldSendRotation) && !(this.entity instanceof AbstractArrow)) {
|
||||
+ if (pos) {
|
||||
+ packet = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) xa, (short) ya, (short) za, this.entity.onGround());
|
||||
+ sentPosition = true;
|
||||
+ } else if (shouldSendRotation) {
|
||||
+ packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), yRotn, xRotn, this.entity.onGround());
|
||||
+ sentRotation = true;
|
||||
+ }
|
||||
+ } else {
|
||||
+ packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short) xa, (short) ya, (short) za, yRotn, xRotn, this.entity.onGround());
|
||||
+ sentPosition = true;
|
||||
+ sentRotation = true;
|
||||
+ }
|
||||
+ }
|
||||
+ // Gale end - Airplane - better checking for useless move packets
|
||||
}
|
||||
|
||||
if (this.entity.needsSync || this.trackDelta || this.entity instanceof LivingEntity livingEntity && livingEntity.isFallFlying()) {
|
||||
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sun, 17 May 2026 10:10:21 +0800
|
||||
Subject: [PATCH] Leaf fast bit radix sort
|
||||
|
||||
This is a part of Leaf(https://github.com/Winds-Studio/Leaf/blob/d0ed97cf45dfa94f686ef32f0eea1ec7323f78d5/leaf-server/minecraft-patches/features/0284-fast-bit-radix-sort.patch)
|
||||
|
||||
Original license: https://github.com/Winds-Studio/Leaf/blob/d0ed97cf45dfa94f686ef32f0eea1ec7323f78d5/LICENSE.md
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 2d5d4170e1f45ae9113c37623b4066861dc79d64..48fea9051efe038a823d7c2c9ae3bf28078f2fcc 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -457,6 +457,7 @@ public final class RegionizedWorldData {
|
||||
public final PathTypeCache pathTypesByPosCache = new PathTypeCache();
|
||||
public final List<LevelChunk> temporaryChunkTickList = new java.util.ArrayList<>();
|
||||
public final Set<ChunkHolder> chunkHoldersToBroadcast = new ReferenceLinkedOpenHashSet<>();
|
||||
+ public final org.dreeam.leaf.util.FastBitRadixSort radixBitSorter = new org.dreeam.leaf.util.FastBitRadixSort();
|
||||
|
||||
// not transient
|
||||
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos;
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
|
||||
index 8aeea55380462421cde43afb4b2fb0ce44b65195..73247b46d778dcb9b3be742e4e4c4c037e3ac0e5 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
|
||||
@@ -15,6 +15,7 @@ public class NearestItemSensor extends Sensor<Mob> {
|
||||
private static final long XZ_RANGE = 32L;
|
||||
private static final long Y_RANGE = 16L;
|
||||
public static final int MAX_DISTANCE_TO_WANTED_ITEM = 32;
|
||||
+ private static final double MAX_DIST_SQ = (double) MAX_DISTANCE_TO_WANTED_ITEM * MAX_DISTANCE_TO_WANTED_ITEM; // Leaf - quick sort
|
||||
|
||||
@Override
|
||||
public Set<MemoryModuleType<?>> requires() {
|
||||
@@ -24,8 +25,16 @@ public class NearestItemSensor extends Sensor<Mob> {
|
||||
@Override
|
||||
protected void doTick(final ServerLevel level, final Mob body) {
|
||||
Brain<?> brain = body.getBrain();
|
||||
- List<ItemEntity> items = level.getEntitiesOfClass(ItemEntity.class, body.getBoundingBox().inflate(32.0, 16.0, 32.0), item -> item.closerThan(body, MAX_DISTANCE_TO_WANTED_ITEM) && body.wantsToPickUp(level, item.getItem())); // Paper - Perf: Move predicate into getEntities
|
||||
- items.sort(Comparator.comparingDouble(body::distanceToSqr));
|
||||
+ // Leaf start - fast bit radix sort
|
||||
+ net.minecraft.core.Position pos = body.position();
|
||||
+ double x = pos.x();
|
||||
+ double y = pos.y();
|
||||
+ double z = pos.z();
|
||||
+ net.minecraft.world.phys.AABB boundingBox = body.getBoundingBox().inflate(32.0, 16.0, 32.0);
|
||||
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<ItemEntity> items = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel) level).moonrise$getEntityLookup().getEntities(ItemEntity.class, null, boundingBox, items, (ItemEntity itemEntity) -> itemEntity.distanceToSqr(x, y, z) < MAX_DIST_SQ && body.wantsToPickUp(level, itemEntity.getItem())); // Paper - Perf: Move predicate into getEntities
|
||||
+ level.getCurrentWorldData().radixBitSorter.sort(items.elements(), items.size(), pos);
|
||||
+ // Leaf end - fast bit radix sort
|
||||
// Paper start - Perf: remove streams from hot code
|
||||
ItemEntity nearest = null;
|
||||
for (final ItemEntity item : items) {
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||||
index 3578ece216827fd5d8c1206c689fc608e97b50df..9fbe439663edf57e018369a44ed7576d947d1fbc 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||||
@@ -17,8 +17,11 @@ public class NearestLivingEntitySensor<T extends LivingEntity> extends Sensor<T>
|
||||
protected void doTick(final ServerLevel level, final T body) {
|
||||
double followRange = body.getAttributeValue(Attributes.FOLLOW_RANGE);
|
||||
AABB boundingBox = body.getBoundingBox().inflate(followRange, followRange, followRange);
|
||||
- List<LivingEntity> livingEntities = level.getEntitiesOfClass(LivingEntity.class, boundingBox, mob -> mob != body && mob.isAlive());
|
||||
- livingEntities.sort(Comparator.comparingDouble(body::distanceToSqr));
|
||||
+ // Leaf start - fast bit radix sort
|
||||
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<LivingEntity> livingEntities = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>();
|
||||
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel) level).moonrise$getEntityLookup().getEntities(LivingEntity.class, body, boundingBox, livingEntities, LivingEntity::isAlive);
|
||||
+ level.getCurrentWorldData().radixBitSorter.sort(livingEntities.elements(), livingEntities.size(), body.position());
|
||||
+ // Leaf end - fast bit radix sort
|
||||
Brain<?> brain = body.getBrain();
|
||||
brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, livingEntities);
|
||||
brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, new NearestVisibleLivingEntities(level, body, livingEntities));
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 27 Jun 2026 17:23:22 +0800
|
||||
Subject: [PATCH] Leaf Configurable vanilla username check
|
||||
|
||||
A part of Leaf(https://github.com/Winds-Studio/Leaf/blob/edb0504069139beaa6f39efa4702370c2576b3fc/leaf-server/minecraft-patches/features/0086-Configurable-vanilla-username-check.patch)
|
||||
|
||||
License: https://github.com/Winds-Studio/Leaf/blob/edb0504069139beaa6f39efa4702370c2576b3fc/LICENSE.md
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 7840b0e00ab84eab016e971ac0c2693056fb0721..d2303ad91c9634cdbf599552a6bce7279a1f0e0a 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -217,7 +217,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public static final NameAndId ANONYMOUS_PLAYER_PROFILE = new NameAndId(Util.NIL_UUID, "Anonymous Player");
|
||||
public static final String SERVER_THREAD_NAME = "Server thread";
|
||||
public LevelStorageSource.LevelStorageAccess storageSource;
|
||||
- protected final PlayerDataStorage playerDataStorage;
|
||||
+ public final PlayerDataStorage playerDataStorage;
|
||||
private final SavedDataStorage savedDataStorage;
|
||||
private final List<Runnable> tickables = Lists.newArrayList();
|
||||
// Paper - per-level GameRules
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index deee051c103f9797f4612e06c12f293ec54724ac..911fb0912c7bc6ab0e29c03a21c6bddb248bbc0a 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -167,11 +167,20 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
public void handleHello(final ServerboundHelloPacket packet) {
|
||||
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet");
|
||||
// Paper start - Validate usernames
|
||||
- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
|
||||
+ // Leaf start - Configurable vanilla username check
|
||||
+ boolean allPrevChecksPassed;
|
||||
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled
|
||||
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
|
||||
&& io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
|
||||
&& !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
|
||||
- Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
|
||||
+ allPrevChecksPassed = true;
|
||||
+ if (!me.earthme.luminol.config.modules.misc.UsernameCheckConfig.allowOldPlayersJoin) {
|
||||
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
|
||||
+ }
|
||||
+ } else {
|
||||
+ allPrevChecksPassed = false;
|
||||
}
|
||||
+ // Leaf end - Configurable vanilla username check
|
||||
this.requestedUuid = packet.profileId();
|
||||
// Paper end - Validate usernames
|
||||
this.requestedUsername = packet.name();
|
||||
@@ -197,6 +206,15 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
authenticatorPool.execute(() -> {
|
||||
try {
|
||||
GameProfile gameprofile = ServerLoginPacketListenerImpl.this.createOfflineProfile(ServerLoginPacketListenerImpl.this.requestedUsername); // Spigot
|
||||
+ // Leaf start - Configurable vanilla username check
|
||||
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.allowOldPlayersJoin) {
|
||||
+ if (server.playerDataStorage.load(new net.minecraft.server.players.NameAndId(gameprofile)).orElse(null) != null) {
|
||||
+ server.getPlayerList().playedPlayers.add(packet.name());
|
||||
+ } else if (allPrevChecksPassed) {
|
||||
+ Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username");
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end - Configurable vanilla username check
|
||||
|
||||
gameprofile = ServerLoginPacketListenerImpl.this.callPlayerPreLoginEvents(gameprofile); // Paper - Add more fields to AsyncPlayerPreLoginEvent
|
||||
ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.name(), gameprofile.id());
|
||||
@@ -341,7 +359,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
server.getPluginManager().callEvent(asyncEvent);
|
||||
profile = asyncEvent.getPlayerProfile();
|
||||
profile.complete(true); // Paper - setPlayerProfileAPI
|
||||
- gameprofile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile);
|
||||
+ gameprofile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopyCustomValidation(profile); // Leaf - Configurable vanilla username check
|
||||
playerName = gameprofile.name();
|
||||
uniqueId = gameprofile.id();
|
||||
// Paper end - Add more fields to AsyncPlayerPreLoginEvent
|
||||
diff --git a/net/minecraft/server/players/CachedUserNameToIdResolver.java b/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
index 7443744e3f256983e52a1cefcaf66082e4a46a7b..b7553611723f7120c66e1f3e51d89df28bd2756b 100644
|
||||
--- a/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
+++ b/net/minecraft/server/players/CachedUserNameToIdResolver.java
|
||||
@@ -67,7 +67,7 @@ public class CachedUserNameToIdResolver implements UserNameToIdResolver {
|
||||
}
|
||||
|
||||
private Optional<NameAndId> lookupGameProfile(final GameProfileRepository profileRepository, final String name) {
|
||||
- if (!StringUtil.isValidPlayerName(name)) {
|
||||
+ if (!StringUtil.isValidPlayerName(name, false)) { // Leaf - Configurable vanilla username check - Directly return, skip unnecessary following logic
|
||||
return this.createUnknownProfile(name);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index a8f051e6aff31a723a3ba59842fac3a43f4911fe..2939aa1ecd68504424198dd7c90c71c6c1aa4c80 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -134,6 +134,7 @@ public abstract class PlayerList {
|
||||
private org.bukkit.craftbukkit.CraftServer cserver;
|
||||
private final Map<String,ServerPlayer> playersByName = new java.util.HashMap<>();
|
||||
public @Nullable String collideRuleTeamName; // Paper - Configurable player collision
|
||||
+ public final List<String> playedPlayers = new java.util.concurrent.CopyOnWriteArrayList<>(); // Leaf - Configurable vanilla username check
|
||||
|
||||
// Folia start - region threading
|
||||
private final Object connectionsStateLock = new Object();
|
||||
@@ -581,6 +582,7 @@ public abstract class PlayerList {
|
||||
player.getAdvancements().clearTriggers();
|
||||
this.players.remove(player);
|
||||
this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
|
||||
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.allowOldPlayersJoin) this.playedPlayers.remove(player.getGameProfile().name()); // Leaf - Configurable vanilla username check
|
||||
this.server.getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer serverPlayer = this.playersByUUID.get(uuid);
|
||||
diff --git a/net/minecraft/util/StringUtil.java b/net/minecraft/util/StringUtil.java
|
||||
index 7957e0cfc43909c5268698a11c4933d20b4d9155..3de226b84f5c72ae277384b3fda4580a7fa2b43d 100644
|
||||
--- a/net/minecraft/util/StringUtil.java
|
||||
+++ b/net/minecraft/util/StringUtil.java
|
||||
@@ -64,6 +64,15 @@ public class StringUtil {
|
||||
}
|
||||
|
||||
public static boolean isValidPlayerName(final String name) {
|
||||
+ // Leaf start - Configurable vanilla username check
|
||||
+ return isValidPlayerName(name, me.earthme.luminol.config.modules.misc.UsernameCheckConfig.shouldSkipNonPlayerNameCheck());
|
||||
+ }
|
||||
+ public static boolean isValidPlayerNameVanilla(final String name) {
|
||||
+ return name.length() <= 16 && name.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty();
|
||||
+ }
|
||||
+ public static boolean isValidPlayerName(final String name, final boolean bypassCheck) {
|
||||
+ if (bypassCheck) return name.length() <= 16;
|
||||
+ // Leaf end - Configurable vanilla username check
|
||||
return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
|
||||
}
|
||||
|
||||
@@ -87,6 +96,12 @@ public class StringUtil {
|
||||
|
||||
// Paper start - Username validation
|
||||
public static boolean isReasonablePlayerName(final String name) {
|
||||
+ // Leaf start - Configurable vanilla username check
|
||||
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.allowOldPlayersJoin && net.minecraft.server.MinecraftServer.getServer().getPlayerList().playedPlayers.contains(name)) return true;
|
||||
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.useCustomUsernameRegex()) {
|
||||
+ return me.earthme.luminol.config.modules.misc.UsernameCheckConfig.usernameRegex.matcher(name).matches() && name.length() <= 16; // Leaf - Configurable username check
|
||||
+ }
|
||||
+ // Leaf end - Configurable vanilla username check
|
||||
if (name.isEmpty() || name.length() > 16) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/component/ResolvableProfile.java b/net/minecraft/world/item/component/ResolvableProfile.java
|
||||
index f1b62a6e0d8176d8ba1875e78cc730ee55b1b0c1..3312a751bdd71080bf429990490061bfbf86b758 100644
|
||||
--- a/net/minecraft/world/item/component/ResolvableProfile.java
|
||||
+++ b/net/minecraft/world/item/component/ResolvableProfile.java
|
||||
@@ -68,6 +68,30 @@ public abstract sealed class ResolvableProfile implements TooltipProvider permit
|
||||
|
||||
public abstract Either<GameProfile, ResolvableProfile.Partial> unpack();
|
||||
|
||||
+ // Leaf start - Configurable vanilla username check - Enforce skull validation
|
||||
+ private static Either<String, UUID> sanitizeDynamicPlayerName(final Either<String, UUID> nameOrId) {
|
||||
+ if (nameOrId.left().isEmpty()) {
|
||||
+ return nameOrId;
|
||||
+ }
|
||||
+ return me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enforceSkullValidation && !net.minecraft.util.StringUtil.isValidPlayerNameVanilla(nameOrId.left().get()) ? Either.left("INVALID_OWNER") : nameOrId;
|
||||
+ }
|
||||
+
|
||||
+ private static Optional<String> sanitizePartialPlayerName(final Optional<String> name) {
|
||||
+ if (name.isEmpty()) {
|
||||
+ return name;
|
||||
+ }
|
||||
+ return me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enforceSkullValidation && !net.minecraft.util.StringUtil.isValidPlayerNameVanilla(name.get()) ? Optional.of("INVALID_OWNER") : name;
|
||||
+ }
|
||||
+
|
||||
+ private static Either<GameProfile, ResolvableProfile.Partial> sanitizeStaticPlayerName(final Either<GameProfile, ResolvableProfile.Partial> contents) {
|
||||
+ if (contents.left().isEmpty()) {
|
||||
+ return contents;
|
||||
+ }
|
||||
+ GameProfile gameProfile = contents.left().get();
|
||||
+ return me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enforceSkullValidation && !net.minecraft.util.StringUtil.isValidPlayerNameVanilla(gameProfile.name()) ? Either.left(new GameProfile(gameProfile.id(), "INVALID_OWNER", gameProfile.properties())) : contents;
|
||||
+ }
|
||||
+ // Leaf end - Configurable vanilla username check - Enforce skull validation
|
||||
+
|
||||
protected ResolvableProfile(final GameProfile partialProfile, final PlayerSkin.Patch skinPatch) {
|
||||
this.partialProfile = partialProfile;
|
||||
this.skinPatch = skinPatch;
|
||||
@@ -96,6 +120,7 @@ public abstract sealed class ResolvableProfile implements TooltipProvider permit
|
||||
private final Either<String, UUID> nameOrId;
|
||||
|
||||
public Dynamic(final Either<String, UUID> nameOrId, final PlayerSkin.Patch skinPatch) {
|
||||
+ sanitizeDynamicPlayerName(nameOrId); // Leaf - Configurable vanilla username check
|
||||
super(ResolvableProfile.createPartialProfile(nameOrId.left(), nameOrId.right(), PropertyMap.EMPTY), skinPatch);
|
||||
this.nameOrId = nameOrId;
|
||||
}
|
||||
@@ -135,6 +160,11 @@ public abstract sealed class ResolvableProfile implements TooltipProvider permit
|
||||
}
|
||||
|
||||
public record Partial(Optional<String> name, Optional<UUID> id, PropertyMap properties) {
|
||||
+ // Leaf start - Configurable vanilla username check
|
||||
+ public Partial {
|
||||
+ name = ResolvableProfile.sanitizePartialPlayerName(name);
|
||||
+ }
|
||||
+ // Leaf end - Configurable vanilla username check
|
||||
public static final ResolvableProfile.Partial EMPTY = new ResolvableProfile.Partial(Optional.empty(), Optional.empty(), PropertyMap.EMPTY);
|
||||
public static final MapCodec<ResolvableProfile.Partial> MAP_CODEC = RecordCodecBuilder.mapCodec(
|
||||
i -> i.group(
|
||||
@@ -165,6 +195,7 @@ public abstract sealed class ResolvableProfile implements TooltipProvider permit
|
||||
private final Either<GameProfile, ResolvableProfile.Partial> contents;
|
||||
|
||||
public Static(final Either<GameProfile, ResolvableProfile.Partial> contents, final PlayerSkin.Patch skinPatch) {
|
||||
+ sanitizeStaticPlayerName(contents); // Leaf - Configurable vanilla username check
|
||||
super(contents.map(gameProfile -> (GameProfile)gameProfile, ResolvableProfile.Partial::createProfile), skinPatch);
|
||||
this.contents = contents;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 10:48:14 +0800
|
||||
Subject: [PATCH] Purpur: Lobotomize stuck villagers
|
||||
|
||||
Co-authored by: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/purpur-server/minecraft-patches/features/0001-Ridables.patch)
|
||||
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
index f649c46cc9a34e646f8da3244866c6e011d30aa3..10715e891205eadd3774dc349c52963606ce1ab7 100644
|
||||
--- a/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/villager/Villager.java
|
||||
@@ -190,6 +190,53 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
||||
this.setCanPickUpLoot(true);
|
||||
}
|
||||
|
||||
+ // Purpur start
|
||||
+ private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur
|
||||
+ private int notLobotomizedCount = 0; // Purpur
|
||||
+
|
||||
+ private boolean checkLobotomized() {
|
||||
+ int interval = me.earthme.luminol.config.modules.optimizations.LobotomizeVillageConfig.villagerLobotomizeCheckInterval;
|
||||
+ boolean shouldCheckForTradeLocked = me.earthme.luminol.config.modules.optimizations.LobotomizeVillageConfig.villagerLobotomizeWaitUntilTradeLocked;
|
||||
+ if (this.notLobotomizedCount > 3) {
|
||||
+ // check half as often if not lobotomized for the last 3+ consecutive checks
|
||||
+ interval *= 2;
|
||||
+ }
|
||||
+ if (this.level().getGameTime() % interval == 0) {
|
||||
+ // offset Y for short blocks like dirt_path/farmland
|
||||
+ this.isLobotomized = !(shouldCheckForTradeLocked && this.getVillagerXp() == 0) && !canTravelFrom(net.minecraft.core.BlockPos.containing(this.position().x, this.getBoundingBox().minY + 0.0625D, this.position().z));
|
||||
+
|
||||
+ if (this.isLobotomized) {
|
||||
+ this.notLobotomizedCount = 0;
|
||||
+ } else {
|
||||
+ this.notLobotomizedCount++;
|
||||
+ }
|
||||
+ }
|
||||
+ return this.isLobotomized;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
+
|
||||
+ private boolean canTravelFrom(net.minecraft.core.BlockPos pos) {
|
||||
+ return canTravelTo(pos.east()) || canTravelTo(pos.west()) || canTravelTo(pos.north()) || canTravelTo(pos.south());
|
||||
+ }
|
||||
+
|
||||
+ private boolean canTravelTo(net.minecraft.core.BlockPos pos) {
|
||||
+ net.minecraft.world.level.block.state.BlockState state = this.level().getBlockStateIfLoaded(pos);
|
||||
+ if (state == null) {
|
||||
+ // chunk not loaded
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.world.level.block.Block bottom = state.getBlock();
|
||||
+ if (bottom instanceof net.minecraft.world.level.block.FenceBlock ||
|
||||
+ bottom instanceof net.minecraft.world.level.block.FenceGateBlock ||
|
||||
+ bottom instanceof net.minecraft.world.level.block.WallBlock) {
|
||||
+ // bottom block is too tall to get over
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.world.level.block.Block top = level().getBlockState(pos.above()).getBlock();
|
||||
+ // only if both blocks have no collision
|
||||
+ return !bottom.hasCollision && !top.hasCollision;
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public Brain<Villager> getBrain() {
|
||||
return (Brain<Villager>)super.getBrain();
|
||||
@@ -259,11 +306,20 @@ public class Villager extends AbstractVillager implements VillagerDataHolder, Re
|
||||
// Paper start - EAR 2
|
||||
this.customServerAiStep(level, false);
|
||||
}
|
||||
- protected void customServerAiStep(ServerLevel level, final boolean inactive) {
|
||||
+ protected void customServerAiStep(ServerLevel level, boolean inactive) { // Purpur - not final
|
||||
// Paper end - EAR 2
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("villagerBrain");
|
||||
+ // Purpur start
|
||||
+ if (me.earthme.luminol.config.modules.optimizations.LobotomizeVillageConfig.villagerLobotomizeEnabled) {
|
||||
+ // treat as inactive if lobotomized
|
||||
+ inactive = inactive || checkLobotomized();
|
||||
+ } else {
|
||||
+ this.isLobotomized = false;
|
||||
+ }
|
||||
+ // Purpur end
|
||||
if (!inactive) this.getBrain().tick(level, this); // Paper - EAR 2
|
||||
+ else if (this.isLobotomized && shouldRestock(level)) restock(); // Purpur - Lobotomize stuck villagers
|
||||
profiler.pop();
|
||||
if (this.assignProfessionWhenSpawned) {
|
||||
this.assignProfessionWhenSpawned = false;
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 21:47:48 +0800
|
||||
Subject: [PATCH] Pufferfish: Reduce projectile chunk loading
|
||||
|
||||
A part of Pufferfish(https://github.com/Pufferfish-gg/Pufferfish)
|
||||
Co-authored-by: Paul Sauve <paul@technove.co>
|
||||
Original patch: https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/pufferfish-server/minecraft-patches/features/0006-Reduce-projectile-chunk-loading.patch
|
||||
Original license(GPL-3.0): https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/PATCH-LICENSE
|
||||
|
||||
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
index 48fea9051efe038a823d7c2c9ae3bf28078f2fcc..c9f2d54be6f0699c2bf922c66ba0bafc7fb83ccc 100644
|
||||
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
||||
@@ -339,6 +339,10 @@ public final class RegionizedWorldData {
|
||||
|
||||
private RegionizedServer.WorldLevelData tickData;
|
||||
|
||||
+ // Luminol start - Pufferfish projectile limiter
|
||||
+ public long pufferfish$loadedThisTick = 0L;
|
||||
+ public long pufferfish$loadedTick = 0L;
|
||||
+ // Luminol end
|
||||
// connections
|
||||
public final List<Connection> connections = new ArrayList<>();
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
index 721e3b083846fd363a31311196bc4c681969215c..81aafd64cc80038eaafba059373db3682afb8c2c 100644
|
||||
--- a/net/minecraft/world/entity/projectile/Projectile.java
|
||||
+++ b/net/minecraft/world/entity/projectile/Projectile.java
|
||||
@@ -58,6 +58,38 @@ public abstract class Projectile extends Entity implements TraceableEntity {
|
||||
this.setOwner(EntityReference.of(owner));
|
||||
}
|
||||
|
||||
+ // Pufferfish start
|
||||
+ private int loadedLifetime = 0;
|
||||
+ @Override
|
||||
+ public void setPos(double x, double y, double z) {
|
||||
+ var currRegionData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData();
|
||||
+ // we might run this on a chunk system worker(chunk gen), so skip this check if no world data was fetched
|
||||
+ if (currRegionData == null || currRegionData.world != this.level()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ long currentTick = currRegionData.getRedstoneGameTime();
|
||||
+ if (currRegionData.pufferfish$loadedTick != currentTick) {
|
||||
+ currRegionData.pufferfish$loadedTick = currentTick;
|
||||
+ currRegionData.pufferfish$loadedThisTick = 0L;
|
||||
+ }
|
||||
+ int previousX = Mth.floor(this.getX()) >> 4, previousZ = Mth.floor(this.getZ()) >> 4;
|
||||
+ int newX = Mth.floor(x) >> 4, newZ = Mth.floor(z) >> 4;
|
||||
+ if (previousX != newX || previousZ != newZ) {
|
||||
+ boolean isLoaded = ((net.minecraft.server.level.ServerChunkCache) this.level().getChunkSource()).getChunkAtIfLoadedImmediately(newX, newZ) != null;
|
||||
+ if (!isLoaded) {
|
||||
+ if (currRegionData.pufferfish$loadedThisTick > me.earthme.luminol.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerTick) {
|
||||
+ if (++this.loadedLifetime > me.earthme.luminol.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerProjectile) {
|
||||
+ this.discard();
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ currRegionData.pufferfish$loadedThisTick++;
|
||||
+ }
|
||||
+ }
|
||||
+ super.setPos(x, y, z);
|
||||
+ }
|
||||
+ // Pufferfish end
|
||||
+
|
||||
// Folia start - region threading
|
||||
// In general, this is an entire mess. At the time of writing, there are fifty usages of getOwner.
|
||||
// Usage of this function is to avoid concurrency issues, even if it sacrifices behavior.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 21:48:40 +0800
|
||||
Subject: [PATCH] Pufferfish: Throttle goal selector during inactive ticking
|
||||
|
||||
A part of Pufferfish(https://github.com/Pufferfish-gg/Pufferfish)
|
||||
Co-authored-by: Kevin Raneri <kevin.raneri@gmail.com>
|
||||
Original patch: https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/pufferfish-server/minecraft-patches/features/0015-Throttle-goal-selector-during-inactive-ticking.patch
|
||||
Original license(GPL-3.0): https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/PATCH-LICENSE
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 301e75393d1074eca0c8533219f516b6d625a38a..24171563af7c629bf2bf492fdc575e2bc67c361e 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -215,12 +215,14 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
return this.lookControl;
|
||||
}
|
||||
|
||||
+ int _pufferfish_inactiveTickDisableCounter = 0; // Pufferfish - throttle inactive goal selector ticking
|
||||
// Paper start
|
||||
@Override
|
||||
public void inactiveTick() {
|
||||
super.inactiveTick();
|
||||
if (!this.aware) return; // Paper - Do not tick AI for inactive unaware mobs
|
||||
- if (this.goalSelector.inactiveTick()) {
|
||||
+ boolean isThrottled = me.earthme.luminol.config.modules.optimizations.EntityGoalSelectorInactiveTickConfig.enabled && _pufferfish_inactiveTickDisableCounter++ % 20 != 0; // Pufferfish - throttle inactive goal selector ticking
|
||||
+ if (this.goalSelector.inactiveTick() && !isThrottled) { // Pufferfish
|
||||
this.goalSelector.tick();
|
||||
}
|
||||
if (this.targetSelector.inactiveTick()) {
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:30:47 +0800
|
||||
Subject: [PATCH] Petal: Reduce sensor work
|
||||
|
||||
Co-authored by: peaches94 <peachescu94@gmail.com>
|
||||
As part of: Petal (https://github.com/Bloom-host/Petal/blob/cc691540fb48240f38b376f3d94c8b0db2b60d99/patches/server/0005-feat-reduce-sensor-work.patch)
|
||||
Licensed under: GPL-3.0 (https://github.com/Bloom-host/Petal/blob/cc691540fb48240f38b376f3d94c8b0db2b60d99/LICENSE)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 24171563af7c629bf2bf492fdc575e2bc67c361e..e7ebdbb8d77f841551c5ebb0f8e7b4402f6a4751 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -842,11 +842,12 @@ public abstract class Mob extends LivingEntity implements Targeting, EquipmentUs
|
||||
return;
|
||||
}
|
||||
// Paper end - Allow nerfed mobs to jump and float
|
||||
+ int idBasedTickCount = this.tickCount + this.getId(); // Luminol - Petal - Move up
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("sensing");
|
||||
- this.sensing.tick();
|
||||
+ if (idBasedTickCount % me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.delayTicks == 0 || !me.earthme.luminol.config.modules.optimizations.PetalReduceSensorWorkConfig.enabled) this.sensing.tick(); // Luminol - Petal - Reduce sensor work
|
||||
profiler.pop();
|
||||
- int idBasedTickCount = this.tickCount + this.getId();
|
||||
+ //int idBasedTickCount = this.tickCount + this.getId(); // Luminol - Petal - Move up
|
||||
if (idBasedTickCount % 2 != 0 && this.tickCount > 1) {
|
||||
profiler.push("targetSelector");
|
||||
this.targetSelector.tickRunningGoals(false);
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 20:57:48 +0800
|
||||
Subject: [PATCH] Leaves: Disable packet limit
|
||||
|
||||
|
||||
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
|
||||
index ecaa296f576c5c90fda89e0406d6552628ef5de3..d2e9d46bbd9ee4ce45419b11499d7a7bc50f0219 100644
|
||||
--- a/net/minecraft/network/Connection.java
|
||||
+++ b/net/minecraft/network/Connection.java
|
||||
@@ -258,8 +258,8 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (this.stopReadingPackets) {
|
||||
return;
|
||||
}
|
||||
- if (this.allPacketCounts != null ||
|
||||
- io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ if (!me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable && (this.allPacketCounts != null || // Luminol - Add config to force disable the packet limiter of Paper
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass()))) { // Luminol - Add config to force disable the packet limiter of Paper
|
||||
long time = System.nanoTime();
|
||||
synchronized (PACKET_LIMIT_LOCK) {
|
||||
if (this.allPacketCounts != null) {
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index a2146662c8ec83f62547bcd813c0e4dcb10efc07..31c6defd8941a2c9e55eca3c8ca5623111e98e51 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -892,7 +892,7 @@ public class ServerGamePacketListenerImpl
|
||||
public void handleCustomCommandSuggestions(final ServerboundCommandSuggestionPacket packet) {
|
||||
// PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); // Paper - AsyncTabCompleteEvent; run this async
|
||||
// CraftBukkit start
|
||||
- if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.nameAndId()) && !this.server.isSingleplayerOwner(this.player.nameAndId())) { // Paper - configurable tab spam limits
|
||||
+ if (!me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable && !this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.nameAndId()) && !this.server.isSingleplayerOwner(this.player.nameAndId())) { // Paper - configurable tab spam limits // Leaves - can disable
|
||||
this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -2128,6 +2128,7 @@ public class ServerGamePacketListenerImpl
|
||||
private long lastLimitedPacket = -1;
|
||||
|
||||
private boolean checkLimit(long timestamp) {
|
||||
+ if (me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable) return true; // Leaves - disable
|
||||
if (!io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.incomingPacketThreshold.enabled()) {
|
||||
return true;
|
||||
}
|
||||
@@ -2694,6 +2695,8 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
// Spigot start - spam exclusions
|
||||
private void detectRateSpam(final TickThrottler throttler, final String message) {
|
||||
+ if (me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable) return; // Leaves - disable
|
||||
+ // CraftBukkit start - replaced with thread safe throttle
|
||||
if (org.spigotmc.SpigotConfig.enableSpamExclusions) {
|
||||
for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
if (exclude != null && message.startsWith(exclude)) {
|
||||
@@ -3492,7 +3495,7 @@ public class ServerGamePacketListenerImpl
|
||||
@Override
|
||||
public void handlePlaceRecipe(final ServerboundPlaceRecipePacket packet) {
|
||||
// Paper start - auto recipe limit
|
||||
- if (!org.bukkit.Bukkit.isPrimaryThread()) {
|
||||
+ if (!me.earthme.luminol.config.modules.misc.PaperPacketLimiterConfig.forceDisable && !org.bukkit.Bukkit.isPrimaryThread()) { // Leaves - can disable
|
||||
if (!this.recipeSpamPackets.isIncrementAndUnderThreshold()) {
|
||||
this.disconnectAsync(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:04:49 +0800
|
||||
Subject: [PATCH] Leaves Vanilla Hopper
|
||||
|
||||
A part from leaves
|
||||
|
||||
Origin patch link: https://github.com/LeavesMC/Leaves/blob/master/leaves-server/minecraft-patches/features/0092-Vanilla-hopper.patch
|
||||
Origin license: https://github.com/LeavesMC/Leaves/blob/master/LICENSE.md
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index a858cb658af70f07614fa1f4d9e8a3435d5c161f..4c9d0bcd8820b250b51c06fff4531021ab57d408 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -281,36 +281,55 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
ItemStack movedItem = origItemStack;
|
||||
final int originalItemCount = origItemStack.getCount();
|
||||
final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount);
|
||||
- container.setChanged(); // original logic always marks source inv as changed even if no move happens.
|
||||
- movedItem.setCount(movedItemCount);
|
||||
-
|
||||
- if (!worldData.skipPullModeEventFire) { // Folia - region threading
|
||||
- movedItem = callPullMoveEvent(hopper, container, movedItem);
|
||||
- if (movedItem == null) { // cancelled
|
||||
- origItemStack.setCount(originalItemCount);
|
||||
- // Drastically improve performance by returning true.
|
||||
- // No plugin could have relied on the behavior of false as the other call
|
||||
- // site for IMIE did not exhibit the same behavior
|
||||
+ // Leaves start - fix vanilla hopper
|
||||
+ if (movedItem.getCount() <= movedItemCount) {
|
||||
+ if (!worldData.skipPullModeEventFire) {
|
||||
+ movedItem = callPullMoveEvent(hopper, container, movedItem);
|
||||
+ if (movedItem == null) { // cancelled
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ movedItem = origItemStack.copy();
|
||||
+ final ItemStack remainingItem = addItem(container, hopper, container.removeItem(i, movedItemCount), null);
|
||||
+ if (remainingItem.isEmpty()) {
|
||||
+ container.setChanged();
|
||||
return true;
|
||||
}
|
||||
- }
|
||||
+ container.setItem(i, movedItem);
|
||||
+ } else {
|
||||
+ container.setChanged(); // original logic always marks source inv as changed even if no move happens.
|
||||
+ movedItem.setCount(movedItemCount);
|
||||
|
||||
- final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
||||
- final int remainingItemCount = remainingItem.getCount();
|
||||
- if (remainingItemCount != movedItemCount) {
|
||||
- origItemStack = origItemStack.copy(true);
|
||||
- origItemStack.setCount(originalItemCount);
|
||||
- if (!origItemStack.isEmpty()) {
|
||||
- origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
||||
+ if (!worldData.skipPullModeEventFire) {
|
||||
+ movedItem = callPullMoveEvent(hopper, container, movedItem);
|
||||
+ if (movedItem == null) { // cancelled
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
+ // Drastically improve performance by returning true.
|
||||
+ // No plugin could have relied on the behavior of false as the other call
|
||||
+ // site for IMIE did not exhibit the same behavior
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
|
||||
- IGNORE_TILE_UPDATES.set(true); // Folia - region threading
|
||||
- container.setItem(i, origItemStack);
|
||||
- IGNORE_TILE_UPDATES.set(false); // Folia - region threading
|
||||
- container.setChanged();
|
||||
- return true;
|
||||
+ final ItemStack remainingItem = addItem(container, hopper, movedItem, null);
|
||||
+ final int remainingItemCount = remainingItem.getCount();
|
||||
+ if (remainingItemCount != movedItemCount) {
|
||||
+ origItemStack = origItemStack.copy(true);
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
+ if (!origItemStack.isEmpty()) {
|
||||
+ origItemStack.setCount(originalItemCount - movedItemCount + remainingItemCount);
|
||||
+ }
|
||||
+
|
||||
+ IGNORE_TILE_UPDATES.set(true);
|
||||
+ container.setItem(i, origItemStack);
|
||||
+ IGNORE_TILE_UPDATES.set(false);
|
||||
+ container.setChanged();
|
||||
+ return true;
|
||||
+ }
|
||||
+ origItemStack.setCount(originalItemCount);
|
||||
}
|
||||
- origItemStack.setCount(originalItemCount);
|
||||
+ // Leaves end - fix vanilla hopper
|
||||
|
||||
if (level.paperConfig().hopper.cooldownWhenFull) {
|
||||
applyCooldown(hopper);
|
||||
+2739
File diff suppressed because it is too large
Load Diff
+56
@@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:26:25 +0800
|
||||
Subject: [PATCH] Leaves: Configurable collision behavior
|
||||
|
||||
Co-authored by: Fortern <blueten.ki@gmail.com>
|
||||
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/c5f18b7864206cea4411211b51787f10affbcb9c/leaves-server/minecraft-patches/features/0111-Configurable-collision-behavior.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
|
||||
index 8d2518600ad518999b75124f0a87db9efe541f2e..09e1d701038042052fcbde4b4686da5d6a15f695 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 - Configurable collision behavior
|
||||
+ public static boolean voxelShapeIntersectVanilla(final AABB box1, final 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 - Configurable collision behavior
|
||||
+
|
||||
// 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 &&
|
||||
@@ -2033,7 +2041,7 @@ public final class CollisionUtil {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
- if (!voxelShapeIntersect(aabb, singleAABB)) {
|
||||
+ if (shouldSkip(aabb, blockCollision, singleAABB)) { // Leaves - Configurable collision behavior
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2087,6 +2095,18 @@ public final class CollisionUtil {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ // Leaves start - Configurable collision behavior
|
||||
+ private static boolean shouldSkip(AABB aabb, VoxelShape blockCollision, AABB singleAABB) {
|
||||
+ boolean isBlockShape = blockCollision == Shapes.block();
|
||||
+ return switch (me.earthme.luminol.config.modules.fixes.CollisionBehaviorConfig.behaviorMode) {
|
||||
+ case me.earthme.luminol.enums.EnumCollisionBehaviorMode.VANILLA -> !voxelShapeIntersectVanilla(aabb, singleAABB);
|
||||
+ case me.earthme.luminol.enums.EnumCollisionBehaviorMode.PAPER -> !voxelShapeIntersect(aabb, singleAABB);
|
||||
+ default -> isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB);
|
||||
+ // All other value as BLOCK_SHAPE_VANILLA to process
|
||||
+ };
|
||||
+ }
|
||||
+ // Leaves end - Configurable collision behavior
|
||||
+
|
||||
public static boolean getEntityHardCollisions(final Level world, final Entity entity, AABB aabb,
|
||||
final List<AABB> into, final int collisionFlags, final Predicate<Entity> predicate) {
|
||||
final boolean checkOnly = (collisionFlags & COLLISION_FLAG_CHECK_ONLY) != 0;
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 21 Apr 2026 23:35:48 +0800
|
||||
Subject: [PATCH] Leaves: Disable moved wrongly threshold
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/f553c53e4230aa032e54a69b6479f1959ed24a60/patches/removed/server/0099-Disable-moved-wrongly-threshold.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 31c6defd8941a2c9e55eca3c8ca5623111e98e51..164e2101688a9f29ecfa83f62141d8cb9df22ed1 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -644,7 +644,7 @@ public class ServerGamePacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// Paper end - Prevent moving into unloaded chunks
|
||||
- if (movedDist - expectedDist > Math.max(100.0, Mth.square(org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed)) && !this.isSingleplayerOwner()) {
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist - expectedDist > Math.max(100.0, Mth.square(org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed)) && !this.isSingleplayerOwner()) { // Leaves - disable can
|
||||
// CraftBukkit end
|
||||
LOGGER.warn(
|
||||
"{} (vehicle of {}) moved too quickly! {},{},{}", vehicle.getPlainTextName(), this.player.getPlainTextName(), xDist, yDist, zDist
|
||||
@@ -674,7 +674,7 @@ public class ServerGamePacketListenerImpl
|
||||
zDist = targetZ - vehicle.getZ();
|
||||
movedDist = xDist * xDist + yDist * yDist + zDist * zDist;
|
||||
boolean fail = false;
|
||||
- if (movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot // Leaves - disable can
|
||||
fail = true;
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", vehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(movedDist));
|
||||
}
|
||||
@@ -1614,7 +1614,7 @@ public class ServerGamePacketListenerImpl
|
||||
|
||||
if (this.shouldCheckPlayerMovement(isFallFlying)) {
|
||||
float metersPerTick = isFallFlying ? 300.0F : 100.0F;
|
||||
- if (movedDist - expectedDist > Math.max(metersPerTick, Mth.square(org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) deltaPackets * speed))) {
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning && movedDist - expectedDist > Math.max(metersPerTick, Mth.square(org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) deltaPackets * speed))) { // Leaves - disable can
|
||||
// CraftBukkit end
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
@@ -1675,7 +1675,8 @@ public class ServerGamePacketListenerImpl
|
||||
zDist = targetZ - this.player.getZ();
|
||||
movedDist = xDist * xDist + yDist * yDist + zDist * zDist;
|
||||
boolean movedWrongly = false; // Paper - Add fail move event; rename
|
||||
- if (!this.player.isChangingDimension()
|
||||
+ if (!me.earthme.luminol.config.modules.misc.DisableWarningConfig.disableMovedWronglyThresholdWarning // Leaves - disable can
|
||||
+ && !this.player.isChangingDimension()
|
||||
&& movedDist > org.spigotmc.SpigotConfig.movedWronglyThreshold // Spigot
|
||||
&& !this.player.isSleeping()
|
||||
&& !this.player.isCreative()
|
||||
@@ -0,0 +1,95 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Tue, 21 Apr 2026 23:52:23 +0800
|
||||
Subject: [PATCH] Leaves: Optimized dragon respawn
|
||||
|
||||
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/4ade1001e4dd19c47d95c27f0b12df3175697f29/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/dimension/end/EnderDragonFight.java b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
|
||||
index 824ef3f458505569fe5b8efb2055ecea7ba6cc56..3388bf5d2cff00b397af1dd7b9ab93669985b35c 100644
|
||||
--- a/net/minecraft/world/level/dimension/end/EnderDragonFight.java
|
||||
+++ b/net/minecraft/world/level/dimension/end/EnderDragonFight.java
|
||||
@@ -317,7 +317,67 @@ public class EnderDragonFight extends SavedData {
|
||||
return false;
|
||||
}
|
||||
|
||||
+ // Leaves start - optimizedDragonRespawn
|
||||
+ private int cachePortalChunkIteratorX = -8;
|
||||
+ private int cachePortalChunkIteratorZ = -8;
|
||||
+ private int cachePortalOriginIteratorY = -1;
|
||||
+
|
||||
public BlockPattern.@Nullable BlockPatternMatch findExitPortal() {
|
||||
+ if (me.earthme.luminol.config.modules.optimizations.OptimizedDragonRespawnConfig.optimizedRespawn) {
|
||||
+ int i, j;
|
||||
+ for (i = cachePortalChunkIteratorX; i <= 8; ++i) {
|
||||
+ for (j = cachePortalChunkIteratorZ; j <= 8; ++j) {
|
||||
+ LevelChunk worldChunk = this.level.getChunk(i, j);
|
||||
+ for (BlockEntity blockEntity : worldChunk.getBlockEntities().values()) {
|
||||
+ if (blockEntity instanceof net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (blockEntity instanceof TheEndPortalBlockEntity) {
|
||||
+ BlockPattern.BlockPatternMatch blockPatternMatch = this.exitPortalPattern.find(this.level, blockEntity.getBlockPos());
|
||||
+ if (blockPatternMatch != null) {
|
||||
+ BlockPos blockPos = blockPatternMatch.getBlock(3, 3, 3).getPos();
|
||||
+ if (this.exitPortalLocation == null) {
|
||||
+ this.exitPortalLocation = blockPos;
|
||||
+ }
|
||||
+ //No need to judge whether optimizing option is open
|
||||
+ cachePortalChunkIteratorX = i;
|
||||
+ cachePortalChunkIteratorZ = j;
|
||||
+ return blockPatternMatch;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (this.needsStateScanning || this.exitPortalLocation == null) {
|
||||
+ if (cachePortalOriginIteratorY != -1) {
|
||||
+ i = cachePortalOriginIteratorY;
|
||||
+ } else {
|
||||
+ i = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(BlockPos.ZERO)).getY();
|
||||
+ }
|
||||
+ boolean notFirstSearch = false;
|
||||
+ for (j = i; j >= 0; --j) {
|
||||
+ BlockPattern.BlockPatternMatch result2 = null;
|
||||
+ if (notFirstSearch) {
|
||||
+ result2 = org.leavesmc.leaves.util.BlockPatternHelper.partialSearchAround(this.exitPortalPattern, this.level, new BlockPos(EndPodiumFeature.getLocation(BlockPos.ZERO).getY(), j, EndPodiumFeature.getLocation(BlockPos.ZERO).getZ()));
|
||||
+ } else {
|
||||
+ result2 = this.exitPortalPattern.find(this.level, new BlockPos(EndPodiumFeature.getLocation(BlockPos.ZERO).getX(), j, EndPodiumFeature.getLocation(BlockPos.ZERO).getZ()));
|
||||
+ }
|
||||
+ if (result2 != null) {
|
||||
+ if (this.exitPortalLocation == null) {
|
||||
+ this.exitPortalLocation = result2.getBlock(3, 3, 3).getPos();
|
||||
+ }
|
||||
+ cachePortalOriginIteratorY = j;
|
||||
+ return result2;
|
||||
+ }
|
||||
+ notFirstSearch = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Leaves end - optimizedDragonRespawn
|
||||
+
|
||||
ChunkPos chunkOrigin = ChunkPos.containing(this.origin);
|
||||
|
||||
for (int x = -8 + chunkOrigin.x(); x <= 8 + chunkOrigin.x(); x++) {
|
||||
@@ -623,8 +683,12 @@ public class EnderDragonFight extends SavedData {
|
||||
}
|
||||
return false; // CraftBukkit - return value
|
||||
}
|
||||
-
|
||||
public boolean respawnDragon(final List<EndCrystal> crystals) { // CraftBukkit - return boolean
|
||||
+ // Leaves - start optimizedDragonRespawn
|
||||
+ cachePortalChunkIteratorX = -8;
|
||||
+ cachePortalChunkIteratorZ = -8;
|
||||
+ cachePortalOriginIteratorY = -1;
|
||||
+ // Leaves - end optimizedDragonRespawn
|
||||
if (this.dragonKilled && this.respawnStage == null) {
|
||||
for (BlockPattern.BlockPatternMatch portal = this.findExitPortal(); portal != null; portal = this.findExitPortal()) {
|
||||
for (int x = 0; x < this.exitPortalPattern.getWidth(); x++) {
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:22:30 +0800
|
||||
Subject: [PATCH] Gale: Variable entity wake-up duration
|
||||
|
||||
Co-authored by: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
As part of: Gale (https://github.com/GaleMC/Gale/blob/276e903b2688f23b19bdc8d493c0bf87656d2400/patches/server/0054-Variable-entity-wake-up-duration.patch)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
index b4f9f41a56bbc40e90217c0344c070ebdd08c119..6e1c2dcb1ef0b496e3d3bca9353d070488d16f44 100644
|
||||
--- a/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
@@ -61,27 +61,39 @@ public final class ActivationRange {
|
||||
if (entity.activationType == ActivationType.VILLAGER) {
|
||||
if (inactiveFor > config.wakeUpInactiveVillagersEvery && worldData.wakeupInactiveRemainingVillagers > 0) { // Folia - threaded regions
|
||||
worldData.wakeupInactiveRemainingVillagers--; // Folia - threaded regions
|
||||
- return config.wakeUpInactiveVillagersFor;
|
||||
+ return getWakeUpDurationWithVariance(entity, config.wakeUpInactiveVillagersFor); // Gale - variable entity wake-up duration
|
||||
}
|
||||
} else if (entity.activationType == ActivationType.ANIMAL) {
|
||||
if (inactiveFor > config.wakeUpInactiveAnimalsEvery && worldData.wakeupInactiveRemainingAnimals > 0) { // Folia - threaded regions
|
||||
worldData.wakeupInactiveRemainingAnimals--; // Folia - threaded regions
|
||||
- return config.wakeUpInactiveAnimalsFor;
|
||||
+ return getWakeUpDurationWithVariance(entity, config.wakeUpInactiveAnimalsFor); // Gale - variable entity wake-up duration
|
||||
}
|
||||
} else if (entity.activationType == ActivationType.FLYING_MONSTER) {
|
||||
if (inactiveFor > config.wakeUpInactiveFlyingEvery && worldData.wakeupInactiveRemainingFlying > 0) { // Folia - threaded regions
|
||||
worldData.wakeupInactiveRemainingFlying--; // Folia - threaded regions
|
||||
- return config.wakeUpInactiveFlyingFor;
|
||||
+ return getWakeUpDurationWithVariance(entity, config.wakeUpInactiveFlyingFor); // Gale - variable entity wake-up duration
|
||||
}
|
||||
} else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) {
|
||||
if (inactiveFor > config.wakeUpInactiveMonstersEvery && worldData.wakeupInactiveRemainingMonsters > 0) { // Folia - threaded regions
|
||||
worldData.wakeupInactiveRemainingMonsters--; // Folia - threaded regions
|
||||
- return config.wakeUpInactiveMonstersFor;
|
||||
+ return getWakeUpDurationWithVariance(entity, config.wakeUpInactiveMonstersFor); // Gale - variable entity wake-up duration
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ // Gale start - variable entity wake-up duration
|
||||
+ private static final java.util.concurrent.ThreadLocalRandom wakeUpDurationRandom = java.util.concurrent.ThreadLocalRandom.current();
|
||||
+
|
||||
+ private static int getWakeUpDurationWithVariance(Entity entity, int wakeUpDuration) {
|
||||
+ double deviation = me.earthme.luminol.config.modules.optimizations.GaleVariableEntityWakeupConfig.entityWakeUpDurationRatioStandardDeviation;
|
||||
+ if (deviation <= 0) {
|
||||
+ return wakeUpDuration;
|
||||
+ }
|
||||
+ return (int) Math.min(Integer.MAX_VALUE, Math.max(1, Math.round(wakeUpDuration * wakeUpDurationRandom.nextGaussian(1, deviation))));
|
||||
+ }
|
||||
+ // Gale end - variable entity wake-up duration
|
||||
+
|
||||
//static AABB maxBB = new AABB(0, 0, 0, 0, 0, 0); // Folia - threaded regions - replaced by local variable
|
||||
|
||||
/**
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:23:37 +0800
|
||||
Subject: [PATCH] Gale: Replace AI attributes with optimized collections
|
||||
|
||||
Co-authored by: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
2No2Name <2No2Name@web.de>
|
||||
As part of: Gale (https://github.com/GaleMC/Gale/blob/276e903b2688f23b19bdc8d493c0bf87656d2400/patches/server/0087-Replace-AI-attributes-with-optimized-collections.patch)
|
||||
Lithium (https://github.com/CaffeineMC/lithium-fabric)
|
||||
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
index 68bad6752bd313ca3ebde7fd4e3b2c46c5dee3ef..c951a04126a75c7caf046237ae00768a1114c03f 100644
|
||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
@@ -14,9 +14,11 @@ import net.minecraft.resources.Identifier;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class AttributeMap {
|
||||
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new Object2ObjectOpenHashMap<>();
|
||||
- private final Set<AttributeInstance> attributesToSync = new ObjectOpenHashSet<>();
|
||||
- private final Set<AttributeInstance> attributesToUpdate = new ObjectOpenHashSet<>();
|
||||
+ // Gale start - Lithium - replace AI attributes with optimized collections
|
||||
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
||||
+ private final Set<AttributeInstance> attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||
+ private final Set<AttributeInstance> attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||
+ // Gale end - Lithium - replace AI attributes with optimized collections
|
||||
private final AttributeSupplier supplier;
|
||||
|
||||
public AttributeMap(final AttributeSupplier supplier) {
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 18 Apr 2026 12:24:51 +0800
|
||||
Subject: [PATCH] Gale: Skip entity move if movement is zero
|
||||
|
||||
Co-authored by: Martijn Muijsers <martijnmuijsers@live.nl>
|
||||
ishland <ishlandmc@yeah.net>
|
||||
A part of: Gale (https://github.com/GaleMC/Gale/blob/276e903b2688f23b19bdc8d493c0bf87656d2400/patches/server/0103-Skip-entity-move-if-movement-is-zero.patch)
|
||||
VMP (https://github.com/RelativityMC/VMP-fabric)
|
||||
Licensed under: MIT (https://opensource.org/licenses/MIT)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 6b3c691dcc9c9e4a8b2b43110aedd5d5131a9520..d1298c499f6551d7a084f2d1ccd2a2b8b9a2475b 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1155,8 +1155,14 @@ public abstract class Entity
|
||||
private double moveStartY;
|
||||
private double moveStartZ;
|
||||
// Paper end - detailed watchdog information
|
||||
+ private boolean boundingBoxChanged = false; // Gale - VMP - skip entity move if movement is zero
|
||||
|
||||
public void move(final MoverType moverType, Vec3 delta) {
|
||||
+ // Gale start - VMP - skip entity move if movement is zero
|
||||
+ if (!this.boundingBoxChanged && delta.equals(Vec3.ZERO)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Gale end - VMP - skip entity move if movement is zero
|
||||
final Vec3 originalMovement = delta; // Paper - Expose pre-collision velocity
|
||||
// Paper start - detailed watchdog information
|
||||
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot move an entity off-main");
|
||||
@@ -5634,6 +5640,11 @@ public abstract class Entity
|
||||
}
|
||||
|
||||
public final void setBoundingBox(final AABB bb) {
|
||||
+ // Gale start - VMP - skip entity move if movement is zero
|
||||
+ if (!this.bb.equals(bb)) {
|
||||
+ this.boundingBoxChanged = true;
|
||||
+ }
|
||||
+ // Gale end - VMP - skip entity move if movement is zero
|
||||
// CraftBukkit start - block invalid bounding boxes
|
||||
double minX = bb.minX,
|
||||
minY = bb.minY,
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sun, 17 May 2026 08:47:31 +0800
|
||||
Subject: [PATCH] Gale Store mob counts in an array
|
||||
|
||||
License: MIT (https://opensource.org/licenses/MIT)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
This patch is based on the following mixin:
|
||||
"com/ishland/vmp/mixins/general/spawn_density_cap/MixinSpawnDensityCapperDensityCap.java"
|
||||
By: ishland <ishlandmc@yeah.net>
|
||||
As part of: VMP (https://github.com/RelativityMC/VMP-fabric)
|
||||
Licensed under: MIT (https://opensource.org/licenses/MIT)
|
||||
|
||||
diff --git a/net/minecraft/world/level/LocalMobCapCalculator.java b/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
index 5b3808e6ff58d350fe3fd65fb56e8f209e1b2c93..150dfb4c8465dea0139bdbf804a84ce28e8d9023 100644
|
||||
--- a/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
+++ b/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
@@ -42,14 +42,14 @@ public class LocalMobCapCalculator {
|
||||
}
|
||||
|
||||
private static class MobCounts {
|
||||
- private final Object2IntMap<MobCategory> counts = new Object2IntOpenHashMap<>(MobCategory.values().length);
|
||||
+ private final int[] counts = new int[MobCategory.values().length]; // Gale - VMP - store mob counts in an array
|
||||
|
||||
public void add(final MobCategory category) {
|
||||
- this.counts.computeInt(category, (k, count) -> count == null ? 1 : count + 1);
|
||||
+ this.counts[category.ordinal()]++; // Gale - VMP - store mob counts in an array
|
||||
}
|
||||
|
||||
public boolean canSpawn(final MobCategory category) {
|
||||
- return this.counts.getOrDefault(category, 0) < category.getMaxInstancesPerChunk();
|
||||
+ return this.counts[category.ordinal()] < category.getMaxInstancesPerChunk(); // Gale - VMP - store mob counts in an array
|
||||
}
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:15:00 +0800
|
||||
Subject: [PATCH] Gale: Optimize random calls in chunk ticking
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
This patch is based on the following patch:
|
||||
"Optimize random calls in chunk ticking"
|
||||
By: Paul Sauve <paul@technove.co>
|
||||
As part of: Airplane (https://github.com/TECHNOVE/Airplane)
|
||||
Licensed under: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
The patch also received the following subsequent modification:
|
||||
By: Kevin Raneri <kevin.raneri@gmail.com>
|
||||
As part of: Pufferfish (https://github.com/pufferfish-gg/Pufferfish)
|
||||
Licensed under: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
* Description *
|
||||
|
||||
Throttling of ice and snow tick has been moved to another patch as
|
||||
configurable ice and snow tick chance.
|
||||
|
||||
* Airplane description *
|
||||
|
||||
Especially at over 30,000 chunks these random calls are fairly heavy. We
|
||||
use a different method here for checking lightning, and for checking
|
||||
ice.
|
||||
|
||||
Lightning: Each chunk now keeps an int of how many ticks until the
|
||||
lightning should strike. This int is a random number from 0 to 100000 * 2,
|
||||
the multiplication is required to keep the probability the same.
|
||||
|
||||
Ice and snow: We just generate a single random number 0-16 and increment
|
||||
it, while checking if it's 0 for the current chunk.
|
||||
|
||||
Depending on configuration for things that tick in a chunk, this is a
|
||||
5-10% improvement.
|
||||
|
||||
* Airplane copyright *
|
||||
|
||||
Airplane
|
||||
Copyright (C) 2020 Technove LLC
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 85eed61919b3c2ef93943e1c1b50fbcbca6fb319..3fda5043937af3d66ab44c41b7e76822a3ddf53b 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1059,7 +1059,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
}
|
||||
|
||||
// Paper start - optimise random ticking
|
||||
- private final io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource simpleRandom = io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource.INSTANCE; // Folia - region threading
|
||||
+ public final io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource simpleRandom = io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource.INSTANCE; // Folia - region threading // Luminol - Make public for : Gale: Optimize random calls in chunk ticking
|
||||
|
||||
private void optimiseRandomTick(final LevelChunk chunk, final int tickSpeed) {
|
||||
final LevelChunkSection[] sections = chunk.getSections();
|
||||
@@ -1141,7 +1141,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
|
||||
int minZ = chunkPos.getMinBlockZ();
|
||||
ProfilerFiller profiler = Profiler.get();
|
||||
profiler.push("thunder");
|
||||
- if (!this.paperConfig().environment.disableThunder && raining && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder
|
||||
+ if (!this.paperConfig().environment.disableThunder && raining && this.isThundering() && this.spigotConfig.thunderChance > 0 /*&& this.random.nextInt(this.spigotConfig.thunderChance) == 0*/ && chunk.shouldDoLightning(this.random)) { // Spigot // Paper - Option to disable thunder // Gale - Airplane - optimize random calls in chunk ticking - replace random with shouldDoLightning
|
||||
BlockPos pos = this.findLightningTargetAround(this.getBlockRandomPos(minX, 0, minZ, 15));
|
||||
if (this.isRainingAt(pos)) {
|
||||
DifficultyInstance difficulty = this.getCurrentDifficultyAt(pos);
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a74eb2079863e4aaa8e982497c0fcd890d7de44b..3a727763cfee696c9fc87dda90260558936043bf 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -144,6 +144,19 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
}
|
||||
// Paper end - get block chunk optimisation
|
||||
|
||||
+ // Gale start - Airplane - optimize random calls in chunk ticking - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
|
||||
+ private int lightningTick;
|
||||
+ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline
|
||||
+ public final boolean shouldDoLightning(net.minecraft.util.RandomSource random) {
|
||||
+ if (this.lightningTick-- <= 0) {
|
||||
+ this.lightningTick = random.nextInt(this.level.spigotConfig.thunderChance) << 1;
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Gale end - Airplane - optimize random calls in chunk ticking - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively
|
||||
+
|
||||
+
|
||||
public LevelChunk(final Level level, final ChunkPos pos) {
|
||||
this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null);
|
||||
}
|
||||
@@ -180,6 +193,8 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
||||
this.debug = !empty && this.level.isDebug();
|
||||
this.defaultBlockState = empty ? VOID_AIR_BLOCKSTATE : AIR_BLOCKSTATE;
|
||||
// Paper end - get block chunk optimisation
|
||||
+
|
||||
+ this.lightningTick = io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource.INSTANCE.nextInt(100000) << 1; // Gale - Airplane - optimize random calls in chunk ticking - initialize lightning tick
|
||||
}
|
||||
|
||||
public LevelChunk(final ServerLevel level, final ProtoChunk protoChunk, final LevelChunk.@Nullable PostLoadProcessor postLoad) {
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:22:55 +0800
|
||||
Subject: [PATCH] Gale: Reduce enderman teleport chunk lookups
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
This patch is based on the following patch:
|
||||
"Reduce chunk loading & lookups"
|
||||
By: Paul Sauve <paul@technove.co>
|
||||
As part of: Airplane (https://github.com/TECHNOVE/Airplane)
|
||||
Licensed under: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
* Airplane copyright *
|
||||
|
||||
Airplane
|
||||
Copyright (C) 2020 Technove LLC
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java
|
||||
index 9b4ae8afda1f2202761cb49bc4f1181ce4eb55d5..d2ac2a0c5bb18c2bca18e5166ed65afd01166e04 100644
|
||||
--- a/net/minecraft/world/entity/monster/EnderMan.java
|
||||
+++ b/net/minecraft/world/entity/monster/EnderMan.java
|
||||
@@ -298,11 +298,19 @@ public class EnderMan extends Monster implements NeutralMob {
|
||||
private boolean teleport(final double x, final double y, final double z) {
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(x, y, z);
|
||||
|
||||
- while (pos.getY() > this.level().getMinY() && !this.level().getBlockState(pos).blocksMotion()) {
|
||||
+ // Gale start - Airplane - single chunk lookup
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = this.level().getChunkIfLoaded(pos);
|
||||
+
|
||||
+ if (chunk == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ while (pos.getY() > this.level().getMinY() && !chunk.getBlockState(pos).blocksMotion()) {
|
||||
+ // Gale end - Airplane - single chunk lookup
|
||||
pos.move(Direction.DOWN);
|
||||
}
|
||||
|
||||
- BlockState blockState = this.level().getBlockState(pos);
|
||||
+ BlockState blockState = chunk.getBlockState(pos); // Gale - Airplane - single chunk lookup
|
||||
boolean couldStandOn = blockState.blocksMotion();
|
||||
boolean isWet = blockState.getFluidState().is(FluidTags.WATER);
|
||||
if (couldStandOn && !isWet) {
|
||||
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:28:24 +0800
|
||||
Subject: [PATCH] Gale: Cache ShapePairKey hash
|
||||
|
||||
License: LGPL-3.0-only (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
The JMH benchmark of this patch can be found in SunBox's `RecordHashCode`
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
|
||||
index 423c45d7be8ac0c27fd3caa0aa8f15f25ad4a3a6..1af396a051cc47dccb973ca864cf1ec2e8b756ed 100644
|
||||
--- a/net/minecraft/world/level/block/Block.java
|
||||
+++ b/net/minecraft/world/level/block/Block.java
|
||||
@@ -696,7 +696,20 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
- private record ShapePairKey(VoxelShape first, VoxelShape second) {
|
||||
+ // Gale start - cache ShapePairKey hash
|
||||
+ static class ShapePairKey {
|
||||
+
|
||||
+ private final VoxelShape first;
|
||||
+ private final VoxelShape second;
|
||||
+ private final int hash;
|
||||
+
|
||||
+ private ShapePairKey(VoxelShape first, VoxelShape second) {
|
||||
+ this.first = first;
|
||||
+ this.second = second;
|
||||
+ this.hash = System.identityHashCode(this.first) * 31 + System.identityHashCode(this.second);
|
||||
+ }
|
||||
+ // Gale end - cache ShapePairKey hash
|
||||
+
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return o instanceof Block.ShapePairKey that && this.first == that.first && this.second == that.second;
|
||||
@@ -704,7 +717,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
- return System.identityHashCode(this.first) * 31 + System.identityHashCode(this.second);
|
||||
+ return this.hash; // Gale - cache ShapePairKey hash
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:30:18 +0800
|
||||
Subject: [PATCH] Gale: For collision check has physics before same vehicle
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
This patch is based on the following patch:
|
||||
"Swaps the predicate order of collision"
|
||||
By: ㄗㄠˋ ㄑㄧˊ <tsao-chi@the-lingo.org>
|
||||
As part of: Akarin (https://github.com/Akarin-project/Akarin)
|
||||
Licensed under: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index d1298c499f6551d7a084f2d1ccd2a2b8b9a2475b..1888210d014f9c00316059a7ccce086dfb0e3a0f 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -2441,8 +2441,8 @@ public abstract class Entity
|
||||
}
|
||||
|
||||
public void push(final Entity entity) {
|
||||
+ if (!entity.noPhysics && !this.noPhysics) { // Gale - Akarin - collision physics check before vehicle check
|
||||
if (!this.isPassengerOfSameVehicle(entity)) {
|
||||
- if (!entity.noPhysics && !this.noPhysics) {
|
||||
if (this.level.paperConfig().collisions.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper - Collision option for requiring a player participant
|
||||
double xa = entity.getX() - this.getX();
|
||||
double za = entity.getZ() - this.getZ();
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:32:39 +0800
|
||||
Subject: [PATCH] Gale: Skip negligible planar movement multiplication
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 1888210d014f9c00316059a7ccce086dfb0e3a0f..00bc928a19cb877698b34b7c039bee5fe8b5cda5 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -1302,8 +1302,17 @@ public abstract class Entity
|
||||
}
|
||||
}
|
||||
|
||||
- float blockSpeedFactor = this.getBlockSpeedFactor();
|
||||
- this.setDeltaMovement(this.getDeltaMovement().multiply(blockSpeedFactor, 1.0, blockSpeedFactor));
|
||||
+ // Gale start - skip negligible planar movement multiplication
|
||||
+ Vec3 oldDeltaMovement = this.getDeltaMovement();
|
||||
+ if (oldDeltaMovement.x < -1e-6 || oldDeltaMovement.x > 1e-6 || oldDeltaMovement.z < -1e-6 || oldDeltaMovement.z > 1e-6) {
|
||||
+ // Gale end - skip negligible planar movement multiplication
|
||||
+ float blockSpeedFactor = this.getBlockSpeedFactor();
|
||||
+ // Gale start - skip negligible planar movement multiplication
|
||||
+ if (blockSpeedFactor < 1 - 1e-6 || blockSpeedFactor > 1 + 1e-6) {
|
||||
+ this.setDeltaMovement(oldDeltaMovement.multiply(blockSpeedFactor, 1.0, blockSpeedFactor));
|
||||
+ }
|
||||
+ }
|
||||
+ // Gale end - skip negligible planar movement multiplication
|
||||
profiler.pop();
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:34:43 +0800
|
||||
Subject: [PATCH] Gale: Optimize matching item checks
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index 5cbfc9e178b5823f92c0afedb1b0248d34c96292..88a5453ac9e3415b5b5c5e81899b9b13627ca817 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -841,11 +841,11 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
}
|
||||
|
||||
public static boolean isSameItem(final ItemStack a, final ItemStack b) {
|
||||
- return a.is(b.getItem());
|
||||
+ return a == b || a.is(b.getItem()); // Gale - optimize identical item checks
|
||||
}
|
||||
|
||||
public static boolean isSameItemSameComponents(final ItemStack a, final ItemStack b) {
|
||||
- return a.is(b.getItem()) && (a.isEmpty() && b.isEmpty() || Objects.equals(a.components, b.components));
|
||||
+ return a == b || a.is(b.getItem()) && (a.isEmpty() && b.isEmpty() || Objects.equals(a.components, b.components)); // Gale - optimize identical item checks
|
||||
}
|
||||
|
||||
public static boolean matchesIgnoringComponents(final ItemStack a, final ItemStack b, final Predicate<DataComponentType<?>> ignoredPredicate) {
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Sat, 20 Jun 2026 23:16:15 +0800
|
||||
Subject: [PATCH] Gale Reduce lambda and Optional allocation in
|
||||
EntityBasedExplosionDamageCalculator
|
||||
|
||||
License: LGPL-3.0-only (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
This patch is based on the following mixin:
|
||||
"net/caffeinemc/mods/lithium/mixin/alloc/explosion_behavior/EntityBasedExplosionDamageCalculatorMixin.java"
|
||||
By: 2No2Name <2No2Name@web.de>
|
||||
As part of: Lithium (https://github.com/CaffeineMC/lithium)
|
||||
Licensed under: LGPL-3.0-only (https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
index 356a3a0dda09af007c3fbddfe360b38f4d7204ce..aff8d67c9b9797402a3bf6c5bce54af19af0ade7 100644
|
||||
--- a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
+++ b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
@@ -17,8 +17,20 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula
|
||||
public Optional<Float> getBlockExplosionResistance(
|
||||
final Explosion explosion, final BlockGetter level, final BlockPos pos, final BlockState block, final FluidState fluid
|
||||
) {
|
||||
- return super.getBlockExplosionResistance(explosion, level, pos, block, fluid)
|
||||
- .map(resistance -> this.source.getBlockExplosionResistance(explosion, level, pos, block, fluid, resistance));
|
||||
+ // Gale start - Lithium - reduce lambda and Optional allocation in EntityBasedExplosionDamageCalculator
|
||||
+ Optional<Float> optionalBlastResistance = super.getBlockExplosionResistance(explosion, level, pos, block, fluid);
|
||||
+
|
||||
+ if (optionalBlastResistance.isPresent()) {
|
||||
+ float resistance = optionalBlastResistance.get();
|
||||
+ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, level, pos, block, fluid, resistance);
|
||||
+
|
||||
+ if (effectiveExplosionResistance != resistance) {
|
||||
+ return Optional.of(effectiveExplosionResistance);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return optionalBlastResistance;
|
||||
+ // Gale end - Lithium - reduce lambda and Optional allocation in EntityBasedExplosionDamageCalculator
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,441 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
Date: Sun, 28 Jun 2026 22:45:55 +0800
|
||||
Subject: [PATCH] Gale Reduce array allocations
|
||||
|
||||
License: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
Gale - https://github.com/GaleMC/Gale
|
||||
|
||||
Enum's values returns anew array copy of the enums, this behavior is defined in
|
||||
`src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java#visitEnumDef`
|
||||
|
||||
This is a defensive programming strategy to prevent enums from being modified. However,
|
||||
copying is unnecessary if we only have read calls.
|
||||
So we can cache the values result to avoid useless allocations.
|
||||
|
||||
Cached as the array since it does not create iterator on the enhanced for loop,
|
||||
But the list does, and may spend more time than iterating using the array.
|
||||
|
||||
One-time calls are excluded from this patch, since no need.
|
||||
|
||||
The JMH benchmark of this patch can be found in SunBox's `CachedEnumValuesForLoop`
|
||||
|
||||
This patch is based on the following patch:
|
||||
"reduce allocs"
|
||||
By: Simon Gardling <titaniumtown@gmail.com>
|
||||
As part of: JettPack (https://gitlab.com/Titaniumtown/JettPack)
|
||||
Licensed under: GPL-3.0-only (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
index 8d9ce3d301d5f7e4106587ae00adb8dd5b8b6f88..dd8a4e445928d93667702dedbd35ab3e0f94f3be 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
|
||||
@@ -400,7 +400,6 @@ public final class ChunkEntitySlices {
|
||||
|
||||
private static final class BasicEntityList<E extends Entity> {
|
||||
|
||||
- private static final Entity[] EMPTY = new Entity[0];
|
||||
private static final int DEFAULT_CAPACITY = 4;
|
||||
|
||||
private E[] storage;
|
||||
@@ -411,7 +410,7 @@ public final class ChunkEntitySlices {
|
||||
}
|
||||
|
||||
public BasicEntityList(final int cap) {
|
||||
- this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]);
|
||||
+ this.storage = (E[])(cap <= 0 ? me.titaniumtown.ArrayConstants.emptyEntityArray : new Entity[cap]);// Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
@@ -423,7 +422,7 @@ public final class ChunkEntitySlices {
|
||||
}
|
||||
|
||||
private void resize() {
|
||||
- if (this.storage == EMPTY) {
|
||||
+ if (this.storage == me.titaniumtown.ArrayConstants.emptyEntityArray) { // Gale - JettPack - reduce array allocations
|
||||
this.storage = (E[])new Entity[DEFAULT_CAPACITY];
|
||||
} else {
|
||||
this.storage = Arrays.copyOf(this.storage, this.storage.length * 2);
|
||||
diff --git a/net/minecraft/nbt/ByteArrayTag.java b/net/minecraft/nbt/ByteArrayTag.java
|
||||
index 4fc0cfeabf60d4bd0dcfd9814d13858454bc39da..0e4dbc0c736ec2ce4826a81ef561a4cd7a8b974d 100644
|
||||
--- a/net/minecraft/nbt/ByteArrayTag.java
|
||||
+++ b/net/minecraft/nbt/ByteArrayTag.java
|
||||
@@ -144,7 +144,7 @@ public final class ByteArrayTag implements CollectionTag {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
- this.data = new byte[0];
|
||||
+ this.data = me.titaniumtown.ArrayConstants.emptyByteArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/nbt/IntArrayTag.java b/net/minecraft/nbt/IntArrayTag.java
|
||||
index 8ed91b84eb90cfe31993fa32b35263e7adea918e..bf4fe7956ceb8c79427e4d89d458ed30ee1dcb54 100644
|
||||
--- a/net/minecraft/nbt/IntArrayTag.java
|
||||
+++ b/net/minecraft/nbt/IntArrayTag.java
|
||||
@@ -151,7 +151,7 @@ public final class IntArrayTag implements CollectionTag {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
- this.data = new int[0];
|
||||
+ this.data = me.titaniumtown.ArrayConstants.emptyIntArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/nbt/LongArrayTag.java b/net/minecraft/nbt/LongArrayTag.java
|
||||
index fe75d82cb43364ff58a531306bac934cbca4f729..5141d9765dc29f23a2a7f0918d2c76ddfe09fa6f 100644
|
||||
--- a/net/minecraft/nbt/LongArrayTag.java
|
||||
+++ b/net/minecraft/nbt/LongArrayTag.java
|
||||
@@ -150,7 +150,7 @@ public final class LongArrayTag implements CollectionTag {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
- this.data = new long[0];
|
||||
+ this.data = me.titaniumtown.ArrayConstants.emptyLongArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/network/CipherBase.java b/net/minecraft/network/CipherBase.java
|
||||
index 5a1fcd0a552dfcebff351c408a0403a8017930c1..1cdb3a6292133719b2e6b824ed9f78857f7b595e 100644
|
||||
--- a/net/minecraft/network/CipherBase.java
|
||||
+++ b/net/minecraft/network/CipherBase.java
|
||||
@@ -7,8 +7,8 @@ import javax.crypto.ShortBufferException;
|
||||
|
||||
public class CipherBase {
|
||||
private final Cipher cipher;
|
||||
- private byte[] heapIn = new byte[0];
|
||||
- private byte[] heapOut = new byte[0];
|
||||
+ private byte[] heapIn = me.titaniumtown.ArrayConstants.emptyByteArray; // Gale - JettPack - reduce array allocations
|
||||
+ private byte[] heapOut = me.titaniumtown.ArrayConstants.emptyByteArray; // Gale - JettPack - reduce array allocations
|
||||
|
||||
protected CipherBase(final Cipher cipher) {
|
||||
this.cipher = cipher;
|
||||
diff --git a/net/minecraft/network/chat/contents/TranslatableContents.java b/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
index b6973f9b48092676029ff58485ec8b8dece7387b..785f5c6f683ffdb73a70afabc42d6c09abb1e1d8 100644
|
||||
--- a/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
+++ b/net/minecraft/network/chat/contents/TranslatableContents.java
|
||||
@@ -28,7 +28,7 @@ import net.minecraft.util.ExtraCodecs;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class TranslatableContents implements ComponentContents {
|
||||
- public static final Object[] NO_ARGS = new Object[0];
|
||||
+ public static final Object[] NO_ARGS = me.titaniumtown.ArrayConstants.emptyObjectArray; // Gale - JettPack - reduce array allocations
|
||||
public static final Codec<Object> PRIMITIVE_ARG_CODEC = ExtraCodecs.JAVA.validate(TranslatableContents::filterAllowedArguments);
|
||||
private static final Codec<Object> ARG_CODEC = Codec.either(PRIMITIVE_ARG_CODEC, ComponentSerialization.CODEC)
|
||||
.xmap(
|
||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||
index 2e71a1cbabf3405e3e4fd5349a1784d895e7e60c..42de919064680b1a464d813976ca5e69a0bd3b01 100644
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -364,7 +364,7 @@ public class ServerEntity {
|
||||
if (this.entity instanceof LivingEntity livingEntity) {
|
||||
List<Pair<EquipmentSlot, ItemStack>> slots = Lists.newArrayList();
|
||||
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
ItemStack itemStack = livingEntity.getItemBySlot(slot);
|
||||
if (!itemStack.isEmpty()) {
|
||||
slots.add(Pair.of(slot, itemStack.copy()));
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 093c48e2379c01f45277b88f6c1b19b107a46326..b4d8cc8b520266abe1921b5e990c34fce3f1d982 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -1424,7 +1424,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
this.getInventory().getNonEquipmentItems().set(i, net.minecraft.world.item.ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
- for (final EquipmentSlot value : EquipmentSlot.VALUES) {
|
||||
+ for (final EquipmentSlot value : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
if (this.getInventory().equipment.has(value) && !shouldKeepDeathEventItem(event, this.getInventory().equipment.get(value))) {
|
||||
this.getInventory().equipment.set(value, net.minecraft.world.item.ItemStack.EMPTY);
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 164e2101688a9f29ecfa83f62141d8cb9df22ed1..2a383eee714b7da08b552c5bfb3988fad3cadb93 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3027,7 +3027,7 @@ public class ServerGamePacketListenerImpl
|
||||
// SPIGOT-7136 - Allays
|
||||
if (target instanceof net.minecraft.world.entity.animal.allay.Allay || target instanceof net.minecraft.world.entity.animal.equine.AbstractHorse) { // Paper - Fix horse armor desync
|
||||
ServerGamePacketListenerImpl.this.send(new net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket(
|
||||
- target.getId(), java.util.Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values())
|
||||
+ target.getId(), java.util.Arrays.stream(net.minecraft.world.entity.EquipmentSlot.VALUES_ARRAY) // Gale - JettPack - reduce array allocations
|
||||
.map((slot) -> com.mojang.datafixers.util.Pair.of(slot, ((LivingEntity) target).getItemBySlot(slot).copy()))
|
||||
.collect(Collectors.toList()), true)); // Paper - sanitize
|
||||
player.containerMenu.sendAllDataToRemote();
|
||||
diff --git a/net/minecraft/server/players/StoredUserList.java b/net/minecraft/server/players/StoredUserList.java
|
||||
index cf6c71db3dd39094608755998ceff6ca067238f3..1353fdfb68d8dbedafd64ac69d2869b22c6bfe09 100644
|
||||
--- a/net/minecraft/server/players/StoredUserList.java
|
||||
+++ b/net/minecraft/server/players/StoredUserList.java
|
||||
@@ -96,7 +96,7 @@ public abstract class StoredUserList<K, V extends StoredUserEntry<K>> {
|
||||
}
|
||||
|
||||
public String[] getUserList() {
|
||||
- return this.map.keySet().toArray(new String[0]);
|
||||
+ return this.map.keySet().toArray(me.titaniumtown.ArrayConstants.emptyStringArray); // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
diff --git a/net/minecraft/util/NullOps.java b/net/minecraft/util/NullOps.java
|
||||
index c7510c99c68c66a64d391b67d93f31cfcd3dccf0..5785ecf52bbd68e6df0f25b917722999addb6a20 100644
|
||||
--- a/net/minecraft/util/NullOps.java
|
||||
+++ b/net/minecraft/util/NullOps.java
|
||||
@@ -171,7 +171,7 @@ public class NullOps implements DynamicOps<Unit> {
|
||||
|
||||
@Override
|
||||
public DataResult<ByteBuffer> getByteBuffer(final Unit input) {
|
||||
- return DataResult.success(ByteBuffer.wrap(new byte[0]));
|
||||
+ return DataResult.success(ByteBuffer.wrap(me.titaniumtown.ArrayConstants.emptyByteArray)); // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/util/ZeroBitStorage.java b/net/minecraft/util/ZeroBitStorage.java
|
||||
index 3666c3efd188508153b6482db425648e3ca77dc7..6c52fcac63fb2b79472ff10cb9f544f347a3fcdd 100644
|
||||
--- a/net/minecraft/util/ZeroBitStorage.java
|
||||
+++ b/net/minecraft/util/ZeroBitStorage.java
|
||||
@@ -5,7 +5,7 @@ import java.util.function.IntConsumer;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class ZeroBitStorage implements BitStorage {
|
||||
- public static final long[] RAW = new long[0];
|
||||
+ public static final long[] RAW = me.titaniumtown.ArrayConstants.emptyLongArray; // Gale - JettPack - reduce array allocations
|
||||
private final int size;
|
||||
|
||||
public ZeroBitStorage(final int size) {
|
||||
diff --git a/net/minecraft/world/entity/ConversionType.java b/net/minecraft/world/entity/ConversionType.java
|
||||
index e5e268a1b2e8c1d728d39e66a53a5ad17fa6694f..59514750c3024d0f16512d2cd2c5b79f297c7beb 100644
|
||||
--- a/net/minecraft/world/entity/ConversionType.java
|
||||
+++ b/net/minecraft/world/entity/ConversionType.java
|
||||
@@ -37,7 +37,7 @@ public enum ConversionType {
|
||||
}
|
||||
|
||||
if (params.keepEquipment()) {
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
ItemStack itemStack = from.getItemBySlot(slot);
|
||||
if (!itemStack.isEmpty()) {
|
||||
to.setItemSlot(slot, itemStack.copyAndClear());
|
||||
diff --git a/net/minecraft/world/entity/EquipmentSlot.java b/net/minecraft/world/entity/EquipmentSlot.java
|
||||
index ffb5f07697e9f1fb07f83ea4739c6b9d5a622892..63a9956f4aaf6feb6de2ef59a2211448f816e4fb 100644
|
||||
--- a/net/minecraft/world/entity/EquipmentSlot.java
|
||||
+++ b/net/minecraft/world/entity/EquipmentSlot.java
|
||||
@@ -20,6 +20,7 @@ public enum EquipmentSlot implements StringRepresentable {
|
||||
SADDLE(EquipmentSlot.Type.SADDLE, 0, 1, 7, "saddle");
|
||||
|
||||
public static final int NO_COUNT_LIMIT = 0;
|
||||
+ public static final EquipmentSlot[] VALUES_ARRAY = values(); // Gale - JettPack - reduce array allocations
|
||||
public static final List<EquipmentSlot> VALUES = List.of(values());
|
||||
public static final IntFunction<EquipmentSlot> BY_ID = ByIdMap.continuous(s -> s.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
|
||||
public static final StringRepresentable.EnumCodec<EquipmentSlot> CODEC = StringRepresentable.fromEnum(EquipmentSlot::values);
|
||||
diff --git a/net/minecraft/world/entity/EquipmentSlotGroup.java b/net/minecraft/world/entity/EquipmentSlotGroup.java
|
||||
index e9b1290f24ba30663110abc61310d0a1e784e5a1..0112c19b99c62dde19af1009030c1645297163d9 100644
|
||||
--- a/net/minecraft/world/entity/EquipmentSlotGroup.java
|
||||
+++ b/net/minecraft/world/entity/EquipmentSlotGroup.java
|
||||
@@ -24,6 +24,7 @@ public enum EquipmentSlotGroup implements StringRepresentable, Iterable<Equipmen
|
||||
BODY(9, "body", EquipmentSlot.BODY),
|
||||
SADDLE(10, "saddle", EquipmentSlot.SADDLE);
|
||||
|
||||
+ public static final EquipmentSlotGroup[] VALUES_ARRAY = EquipmentSlotGroup.values(); // Gale - JettPack - reduce array allocations
|
||||
public static final IntFunction<EquipmentSlotGroup> BY_ID = ByIdMap.continuous(s -> s.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
|
||||
public static final Codec<EquipmentSlotGroup> CODEC = StringRepresentable.fromEnum(EquipmentSlotGroup::values);
|
||||
public static final StreamCodec<ByteBuf, EquipmentSlotGroup> STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, s -> s.id);
|
||||
diff --git a/net/minecraft/world/entity/EquipmentTable.java b/net/minecraft/world/entity/EquipmentTable.java
|
||||
index 4b018c64d3123bb7a0687491d2ac3a535302890c..0e4d6c9a35d29c240a0cf30694211ea3db66895c 100644
|
||||
--- a/net/minecraft/world/entity/EquipmentTable.java
|
||||
+++ b/net/minecraft/world/entity/EquipmentTable.java
|
||||
@@ -35,7 +35,7 @@ public record EquipmentTable(ResourceKey<LootTable> lootTable, Map<EquipmentSlot
|
||||
}
|
||||
|
||||
private static Map<EquipmentSlot, Float> createForAllSlots(final float dropChance) {
|
||||
- return createForAllSlots(List.of(EquipmentSlot.values()), dropChance);
|
||||
+ return createForAllSlots(List.of(EquipmentSlot.VALUES_ARRAY), dropChance); // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
private static Map<EquipmentSlot, Float> createForAllSlots(final List<EquipmentSlot> slots, final float dropChance) {
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 1cb8265c1313ad4893d45c344b03007fc4e2de4b..fcaeb471dada57e9ba4d224693cefbff2fa631be 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3609,7 +3609,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
Map<org.bukkit.inventory.EquipmentSlot, io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange> equipmentChanges = null;
|
||||
// Paper end - EntityEquipmentChangedEvent
|
||||
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
ItemStack previous = lastEquipmentItems.get(slot);
|
||||
ItemStack current = this.getItemBySlot(slot);
|
||||
if (this.equipmentHasChanged(previous, current)) {
|
||||
@@ -3892,7 +3892,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
|
||||
|
||||
protected boolean canGlide() {
|
||||
if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) {
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
if (canGlideUsing(this.getItemBySlot(slot), slot)) {
|
||||
return true;
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index 9e4293c6df1851a852423b469577388d2254e169..952b09fba4cf7de90110a7aa4b96dc03afab25e1 100644
|
||||
--- a/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -484,7 +484,7 @@ public class ArmorStand extends LivingEntity {
|
||||
if (this.deathDropItems == null) this.deathDropItems = new java.util.ArrayList<>(); // Paper
|
||||
this.dropAllDeathLoot(level, source);
|
||||
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
this.postDeathEventTasks.add(() -> this.equipment.set(slot, ItemStack.EMPTY)); // Paper - move equipment removal past event call
|
||||
ItemStack itemStack = this.equipment.get(slot); // Paper
|
||||
if (!itemStack.isEmpty() && !EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) {
|
||||
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
|
||||
index a4bc767b799c050ce07a3685f655b4ba947d2466..a447b9fbb579591c62b3d8f8e2527796feefc4a0 100644
|
||||
--- a/net/minecraft/world/entity/player/Player.java
|
||||
+++ b/net/minecraft/world/entity/player/Player.java
|
||||
@@ -346,7 +346,7 @@ public abstract class Player extends Avatar implements ContainerUser {
|
||||
}
|
||||
|
||||
private boolean isEquipped(final Item item) {
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
ItemStack itemStack = this.getItemBySlot(slot);
|
||||
Equippable equippable = itemStack.get(DataComponents.EQUIPPABLE);
|
||||
if (itemStack.is(item) && equippable != null && equippable.slot() == slot) {
|
||||
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
||||
index 88a5453ac9e3415b5b5c5e81899b9b13627ca817..a6805d436fd3675e385cbf8a3e5b262ae694ed90 100644
|
||||
--- a/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/net/minecraft/world/item/ItemStack.java
|
||||
@@ -1182,7 +1182,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance, Chang
|
||||
|
||||
private void addAttributeTooltips(final Consumer<Component> consumer, final TooltipDisplay display, final @Nullable Player player) {
|
||||
if (display.shows(DataComponents.ATTRIBUTE_MODIFIERS)) {
|
||||
- for (EquipmentSlotGroup slot : EquipmentSlotGroup.values()) {
|
||||
+ for (EquipmentSlotGroup slot : EquipmentSlotGroup.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
MutableBoolean first = new MutableBoolean(true);
|
||||
this.forEachModifier(slot, (attribute, modifier, tooltip) -> {
|
||||
if (tooltip != ItemAttributeModifiers.Display.hidden()) {
|
||||
diff --git a/net/minecraft/world/item/crafting/ShapedRecipePattern.java b/net/minecraft/world/item/crafting/ShapedRecipePattern.java
|
||||
index b2ca30b84a6f498a2b18145eb1efaea7c4c5c943..f60e6188d25c13fc433931b0e8760869ccee8fb0 100644
|
||||
--- a/net/minecraft/world/item/crafting/ShapedRecipePattern.java
|
||||
+++ b/net/minecraft/world/item/crafting/ShapedRecipePattern.java
|
||||
@@ -121,7 +121,7 @@ public final class ShapedRecipePattern {
|
||||
}
|
||||
|
||||
if (pattern.size() == bottom) {
|
||||
- return new String[0];
|
||||
+ return me.titaniumtown.ArrayConstants.emptyStringArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
String[] result = new String[pattern.size() - bottom - top];
|
||||
diff --git a/net/minecraft/world/item/enchantment/Enchantment.java b/net/minecraft/world/item/enchantment/Enchantment.java
|
||||
index 0d981b86fa7ee8713e2a419fc2f377defbc2ed9c..26d850a0ee40c5042e99689f8bd67d8859c42d40 100644
|
||||
--- a/net/minecraft/world/item/enchantment/Enchantment.java
|
||||
+++ b/net/minecraft/world/item/enchantment/Enchantment.java
|
||||
@@ -107,7 +107,7 @@ public record Enchantment(Component description, Enchantment.EnchantmentDefiniti
|
||||
public Map<EquipmentSlot, ItemStack> getSlotItems(final LivingEntity entity) {
|
||||
Map<EquipmentSlot, ItemStack> itemStacks = Maps.newEnumMap(EquipmentSlot.class);
|
||||
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
if (this.matchingSlot(slot)) {
|
||||
ItemStack itemStack = entity.getItemBySlot(slot);
|
||||
if (!itemStack.isEmpty()) {
|
||||
diff --git a/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
index ed84782f4fcaec8f12ab68641a42ad6e09079875..4f2017c4ca12dcedb9587e0d3d3c9a6be4996167 100644
|
||||
--- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
+++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java
|
||||
@@ -157,7 +157,7 @@ public class EnchantmentHelper {
|
||||
}
|
||||
|
||||
private static void runIterationOnEquipment(final LivingEntity owner, final EnchantmentHelper.EnchantmentInSlotVisitor method) {
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
runIterationOnItem(owner.getItemBySlot(slot), slot, owner, method);
|
||||
}
|
||||
}
|
||||
@@ -495,7 +495,7 @@ public class EnchantmentHelper {
|
||||
) {
|
||||
List<EnchantedItemInUse> items = new ArrayList<>();
|
||||
|
||||
- for (EquipmentSlot slot : EquipmentSlot.VALUES) {
|
||||
+ for (EquipmentSlot slot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
ItemStack item = source.getItemBySlot(slot);
|
||||
if (predicate.test(item)) {
|
||||
ItemEnchantments enchantments = item.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY);
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 87fb17917f4cecfef2d5d03bf8fd6e61d075212e..000e4924e8e338728715a3946002903a3118a98a 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -1966,7 +1966,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
public org.bukkit.entity.Entity[] getChunkEntities(int chunkX, int chunkZ) {
|
||||
ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices slices = ((ServerLevel)this).moonrise$getEntityLookup().getChunk(chunkX, chunkZ);
|
||||
if (slices == null) {
|
||||
- return new org.bukkit.entity.Entity[0];
|
||||
+ return me.titaniumtown.ArrayConstants.emptyBukkitEntityArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
List<org.bukkit.entity.Entity> ret = new java.util.ArrayList<>();
|
||||
@@ -1977,7 +1977,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
}
|
||||
}
|
||||
|
||||
- return ret.toArray(new org.bukkit.entity.Entity[0]);
|
||||
+ return ret.toArray(me.titaniumtown.ArrayConstants.emptyBukkitEntityArray); // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/ComposterBlock.java b/net/minecraft/world/level/block/ComposterBlock.java
|
||||
index 0c8cc60efc8999e76632c605fa7d2b0cfa347e17..4e0c19970595dd2899a2e08ee122266c2338d84d 100644
|
||||
--- a/net/minecraft/world/level/block/ComposterBlock.java
|
||||
+++ b/net/minecraft/world/level/block/ComposterBlock.java
|
||||
@@ -434,7 +434,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(final Direction direction) {
|
||||
- return new int[0];
|
||||
+ return me.titaniumtown.ArrayConstants.emptyIntArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -469,7 +469,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(final Direction direction) {
|
||||
- return direction == Direction.UP ? new int[]{0} : new int[0];
|
||||
+ return direction == Direction.UP ? me.titaniumtown.ArrayConstants.zeroSingletonIntArray : me.titaniumtown.ArrayConstants.emptyIntArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -521,7 +521,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(final Direction direction) {
|
||||
- return direction == Direction.DOWN ? new int[]{0} : new int[0];
|
||||
+ return direction == Direction.DOWN ? me.titaniumtown.ArrayConstants.zeroSingletonIntArray : me.titaniumtown.ArrayConstants.emptyIntArray; // Gale - JettPack - reduce array allocations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
index 9006438c36771794c9375babffa8c5944a38983d..ac93d2992fe780133439302ce5b851f9ac0c7353 100644
|
||||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -44,7 +44,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
||||
protected static final int SLOT_FUEL = 1;
|
||||
protected static final int SLOT_RESULT = 2;
|
||||
public static final int DATA_LIT_TIME = 0;
|
||||
- private static final int[] SLOTS_FOR_UP = new int[]{0};
|
||||
+ private static final int[] SLOTS_FOR_UP = me.titaniumtown.ArrayConstants.zeroSingletonIntArray; // Gale - JettPack - reduce array allocations
|
||||
private static final int[] SLOTS_FOR_DOWN = new int[]{2, 1};
|
||||
private static final int[] SLOTS_FOR_SIDES = new int[]{1};
|
||||
public static final int DATA_LIT_DURATION = 1;
|
||||
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
index e00caf8dc68ce49f4011f881f3558347fe848822..a9201522bdca5a6e6aae48624d3f95fcb0e3d941 100644
|
||||
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
@@ -268,7 +268,7 @@ public class MapItemSavedData extends SavedData {
|
||||
}
|
||||
|
||||
private static boolean hasMapInvisibilityItemEquipped(final Player player) {
|
||||
- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
|
||||
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
|
||||
if (equipmentSlot != EquipmentSlot.MAINHAND
|
||||
&& equipmentSlot != EquipmentSlot.OFFHAND
|
||||
&& player.getItemBySlot(equipmentSlot).is(ItemTags.MAP_INVISIBILITY_EQUIPMENT)) {
|
||||
@@ -0,0 +1,80 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MrHua269 <mrhua269@gmail.com>
|
||||
Date: Fri, 1 May 2026 21:51:11 +0800
|
||||
Subject: [PATCH] Some optimizations from krypton
|
||||
|
||||
A part of krypton's mixin:
|
||||
|
||||
https://github.com/astei/krypton/blob/master/src/main/java/me/steinborn/krypton/mixin/shared/network/microopt/StringEncodingMixin.java and https://github.com/astei/krypton/blob/master/src/main/java/me/steinborn/krypton/mixin/shared/network/microopt/VarIntsMixin.java
|
||||
|
||||
Original project license: https://github.com/astei/krypton/blob/master/LICENSE
|
||||
|
||||
diff --git a/net/minecraft/network/Utf8String.java b/net/minecraft/network/Utf8String.java
|
||||
index 8b778744a5f01943976f180ad340a1cbce7db506..c46bf9940d4275ac09e8c94c8ae1019312fa90b7 100644
|
||||
--- a/net/minecraft/network/Utf8String.java
|
||||
+++ b/net/minecraft/network/Utf8String.java
|
||||
@@ -33,6 +33,22 @@ public class Utf8String {
|
||||
}
|
||||
|
||||
public static void write(final ByteBuf output, final CharSequence value, final int maxLength) {
|
||||
+ // Luminol start - Krypton optimizations
|
||||
+ if (true) {
|
||||
+ if (value.length() > maxLength) {
|
||||
+ throw new EncoderException("String too big (was " + value.length() + " characters, max " + maxLength + ")");
|
||||
+ }
|
||||
+ int utf8Bytes = ByteBufUtil.utf8Bytes(value);
|
||||
+ int maxBytesPermitted = ByteBufUtil.utf8MaxBytes(maxLength);
|
||||
+ if (utf8Bytes > maxBytesPermitted) {
|
||||
+ throw new EncoderException("String too big (was " + utf8Bytes + " bytes encoded, max " + maxBytesPermitted + ")");
|
||||
+ } else {
|
||||
+ VarInt.write(output, utf8Bytes);
|
||||
+ output.writeCharSequence(value, StandardCharsets.UTF_8);
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ // Luminol end
|
||||
if (value.length() > maxLength) {
|
||||
throw new EncoderException("String too big (was " + value.length() + " characters, max " + maxLength + ")");
|
||||
}
|
||||
diff --git a/net/minecraft/network/VarInt.java b/net/minecraft/network/VarInt.java
|
||||
index 1428ce80e8316a24cfca7b6aafdea8588a5a790e..73b01c4ac8c69f6a984c8f3947cdd2688cd70c14 100644
|
||||
--- a/net/minecraft/network/VarInt.java
|
||||
+++ b/net/minecraft/network/VarInt.java
|
||||
@@ -60,7 +60,8 @@ public class VarInt {
|
||||
int s = (value & 0x7F | 0x80) << 8 | (value >>> 7);
|
||||
output.writeShort(s);
|
||||
} else {
|
||||
- writeSlow(output, value);
|
||||
+ // writeSlow(output, value); // Luminol - Krypton optimizations
|
||||
+ writeVarIntFull(output, value); // Luminol - Krypton optimizations
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -74,4 +75,27 @@ public class VarInt {
|
||||
output.writeByte(value);
|
||||
return output;
|
||||
}
|
||||
+ // Luminol start - Krypton optimizations
|
||||
+ private static void writeVarIntFull(ByteBuf buf, int value) {
|
||||
+ // See https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
|
||||
+ if ((value & (0xFFFFFFFF << 7)) == 0) {
|
||||
+ buf.writeByte(value);
|
||||
+ } else if ((value & (0xFFFFFFFF << 14)) == 0) {
|
||||
+ int w = (value & 0x7F | 0x80) << 8 | (value >>> 7);
|
||||
+ buf.writeShort(w);
|
||||
+ } else if ((value & (0xFFFFFFFF << 21)) == 0) {
|
||||
+ int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14);
|
||||
+ buf.writeMedium(w);
|
||||
+ } else if ((value & (0xFFFFFFFF << 28)) == 0) {
|
||||
+ int w = (value & 0x7F | 0x80) << 24 | (((value >>> 7) & 0x7F | 0x80) << 16)
|
||||
+ | ((value >>> 14) & 0x7F | 0x80) << 8 | (value >>> 21);
|
||||
+ buf.writeInt(w);
|
||||
+ } else {
|
||||
+ int w = (value & 0x7F | 0x80) << 24 | ((value >>> 7) & 0x7F | 0x80) << 16
|
||||
+ | ((value >>> 14) & 0x7F | 0x80) << 8 | ((value >>> 21) & 0x7F | 0x80);
|
||||
+ buf.writeInt(w);
|
||||
+ buf.writeByte(value >>> 28);
|
||||
+ }
|
||||
+ }
|
||||
+ // Luminol end
|
||||
}
|
||||
+2
-2
@@ -5,10 +5,10 @@ Subject: [PATCH] Fix datapack command save function
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index fb5f9176916931b23ebf4a5b7ecdfc5285ffbc2b..ecdcf0db97341d2cb460f86f451cecd5c40dbfee 100644
|
||||
index d2303ad91c9634cdbf599552a6bce7279a1f0e0a..4b6f961e695155db1d6cc86496491017bf3a6383 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2450,6 +2450,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -2460,6 +2460,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return this.reloadResources(packsToEnable, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to disable some check for operators
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index ebede474ca98c82131215913865b9f7bb4d57313..fe6e1aea364620f82de44b942da0d3846c7d17b5 100644
|
||||
index 2a383eee714b7da08b552c5bfb3988fad3cadb93..6f5d5b123f69b7bdc3960e0ad216ec291aa100c3 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -402,7 +402,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -35,7 +35,7 @@ index ebede474ca98c82131215913865b9f7bb4d57313..fe6e1aea364620f82de44b942da0d384
|
||||
fail = true;
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", vehicle.getPlainTextName(), this.player.getPlainTextName(), Math.sqrt(movedDist));
|
||||
}
|
||||
@@ -1606,7 +1606,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1619,7 +1619,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
@@ -44,7 +44,7 @@ index ebede474ca98c82131215913865b9f7bb4d57313..fe6e1aea364620f82de44b942da0d384
|
||||
if (event.getLogWarning()) {
|
||||
LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), xDist, yDist, zDist);
|
||||
}
|
||||
@@ -1672,7 +1672,7 @@ public class ServerGamePacketListenerImpl
|
||||
@@ -1685,7 +1685,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper start - Add fail move event
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY,
|
||||
targetX, targetY, targetZ, targetYRot, targetXRot, true);
|
||||
+1
-1
@@ -48,7 +48,7 @@ index 9800ae1d3c49800b0c7342d43d696109b5b72cf4..f9a8c79640ed6ca381e4482eaeab6b23
|
||||
SaveOnCommand.register(this.dispatcher);
|
||||
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index ecdcf0db97341d2cb460f86f451cecd5c40dbfee..437abeb7b2d021b38b438d0e046f05809e196930 100644
|
||||
index 4b6f961e695155db1d6cc86496491017bf3a6383..e7f7f7927fc1e2ce45ea5dbf7cc9ec19197c599f 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1652,6 +1652,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user