Compare commits

..

28 Commits

Author SHA1 Message Date
MrHua269
f3e8f024a7 Switch dev/1.21.4 to ver/1.21.4 2025-01-11 22:32:31 +08:00
MrHua269
85f21d1be1 Merge Paper #11945 for temporary hooper behavior fix
A hopper optimization fix on Paper's pr : https://github.com/PaperMC/Paper/pull/11945
2025-01-11 18:46:28 +08:00
MrHua269
c0f20000cf Merge Paper #11945 for temporary hooper behavior fix
A hopper optimization fix on Paper's pr : https://github.com/PaperMC/Paper/pull/11945
2025-01-11 18:41:51 +08:00
MrHua269
b33e2fc51d Mark secure seed config "enabled" unhotloadable 2025-01-11 18:20:32 +08:00
MrHua269
b2c753bcfd Make config file loaded earlier than bootstrap 2025-01-11 18:20:05 +08:00
MrHua269
677544289b Try fixing folia #315
Might be useful to https://github.com/PaperMC/Folia/issues/315
2025-01-11 15:24:52 +08:00
Creeam
87d2047f24 [ci skip] Fix typo in workflow file 2025-01-11 00:05:11 +08:00
Dreeam
217047f7b5 Update workflow 2025-01-09 16:37:37 -05:00
Dreeam
2dcdca21b2 Build 2025-01-09 15:59:41 -05:00
MrHua269
7afc1b403c Replaced "-" with "_" in config key names of sentry and secure seed and cleaned patches 2025-01-09 22:38:40 +08:00
M2ke4U
e6e33b3947 Merge pull request #41 from adabugra/feature/sentry
Feature: Add Sentry
2025-01-09 22:29:29 +08:00
adabugra
bebfe1eda7 Add Pufferfish: Sentry 2025-01-06 19:28:34 +03:00
M2ke4U
b9ca4c0c7a Merge pull request #39 from adabugra/feature/secure-seed
Feature: Add Secure Seed
2025-01-05 22:34:51 +08:00
adabugra
12cfb7a0ef Add Leaf: SecureSeed Command 2025-01-05 12:41:42 +03:00
adabugra
e618370375 Add Leaf: Secure Seed 2025-01-05 12:40:57 +03:00
MrHua269
74aeb4fe5d Set old pos before moving entity by piston 2025-01-01 12:19:31 +08:00
MrHua269
102979a7d8 Add descriptions for unsafe teleportation 2025-01-01 10:58:35 +08:00
MrHua269
c5f561233f Added missing descriptions 2024-12-31 17:52:38 +08:00
MrHua269
0d6b9a051f Add config for watchdog timeout 2024-12-31 17:47:06 +08:00
MrHua269
36b617c5be Fix patch conflict 2024-12-31 17:42:31 +08:00
M2ke4U
487fcdfc10 Merge pull request #38 from Leleawa/patch-1
fix color in console
2024-12-31 16:00:02 +08:00
Leleawa
c99f65d958 Create 0053-Leaves-Fix-color-in-console.patch 2024-12-30 11:49:59 +08:00
Dreeam
1984558e49 Added config for tripwire dupe 2024-12-29 17:11:18 -05:00
Dreeam
ab5b160232 Update configurable username check 2024-12-29 17:11:06 -05:00
MrHua269
16df7dce12 Use improved original flush logic on linear region flushing 2024-12-27 15:14:52 +08:00
MrHua269
8a01b9ad39 Rewrite linear flushing 2024-12-26 12:53:23 +08:00
MrHua269
27a2e2a129 Fix wrong end portal teleport position 2024-12-15 15:36:38 +08:00
MrHua269
3b9b3813b4 Fix extension name parsing again *
Jesus what careless I am()
2024-12-15 14:01:21 +08:00
52 changed files with 1782 additions and 223 deletions

View File

@@ -1,10 +1,10 @@
name: Luminol CI - dev/1.21.4
name: Luminol CI - ver/1.21.4
on:
push:
branches: [ "dev/1.21.4" ]
branches: [ "ver/1.21.4" ]
pull_request:
branches: [ "de/1.21.4" ]
branches: [ "ver/1.21.4" ]
permissions: write-all
@@ -22,12 +22,14 @@ jobs:
with:
distribution: 'zulu'
java-version: '22'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Configure Git User Details
run: git config --global user.email "ci@luminolmc.com" && git config --global user.name "LuminolMC CI"
- name: Apply Patches
run: gradle applyPatches
run: ./gradlew applyPatches
- name: CreateJar
run: gradle createMojmapBundlerJar createMojmapPaperclipJar
run: ./gradlew createMojmapPaperclipJar
- name: Publish to repo
continue-on-error: true
run: |

View File

@@ -10,4 +10,4 @@ org.gradle.jvmargs = -Xmx3G
mcVersion = 1.21.4
GroupMCV = 1.21
preVersion = true
preVersion = false

View File

@@ -0,0 +1,243 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: adabugra <57899270+adabugra@users.noreply.github.com>
Date: Mon, 6 Jan 2025 19:24:06 +0300
Subject: [PATCH] Pufferfish: Sentry
diff --git a/build.gradle.kts b/build.gradle.kts
index 1aa76451f9129b578d6887b1239966eb67f5ee1b..2ddad10cf12dd07fd227ddda13336fdd61cd0197 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -66,6 +66,7 @@ dependencies {
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
api("org.apache.logging.log4j:log4j-api:$log4jVersion")
api("org.slf4j:slf4j-api:$slf4jVersion")
+ api("io.sentry:sentry:8.0.0-rc.2") // Pufferfish
implementation("org.ow2.asm:asm:9.7.1")
implementation("org.ow2.asm:asm-commons:9.7.1")
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7772aac00f6db664f7a5673bc2585fa025e6aad
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java
@@ -0,0 +1,165 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import com.google.gson.Gson;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.RegisteredListener;
+import org.jetbrains.annotations.Nullable;
+
+public class SentryContext {
+
+ private static final Gson GSON = new Gson();
+
+ public static void setPluginContext(@Nullable Plugin plugin) {
+ if (plugin != null) {
+ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName());
+ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getPluginMeta().getVersion());
+ }
+ }
+
+ public static void removePluginContext() {
+ ThreadContext.remove("pufferfishsentry_pluginname");
+ ThreadContext.remove("pufferfishsentry_pluginversion");
+ }
+
+ public static void setSenderContext(@Nullable CommandSender sender) {
+ if (sender != null) {
+ ThreadContext.put("pufferfishsentry_playername", sender.getName());
+ if (sender instanceof Player player) {
+ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString());
+ }
+ }
+ }
+
+ public static void removeSenderContext() {
+ ThreadContext.remove("pufferfishsentry_playername");
+ ThreadContext.remove("pufferfishsentry_playerid");
+ }
+
+ public static void setEventContext(Event event, RegisteredListener registration) {
+ setPluginContext(registration.getPlugin());
+
+ try {
+ // Find the player that was involved with this event
+ Player player = null;
+ if (event instanceof PlayerEvent) {
+ player = ((PlayerEvent) event).getPlayer();
+ } else {
+ Class<? extends Event> eventClass = event.getClass();
+
+ Field playerField = null;
+
+ for (Field field : eventClass.getDeclaredFields()) {
+ if (field.getType().equals(Player.class)) {
+ playerField = field;
+ break;
+ }
+ }
+
+ if (playerField != null) {
+ playerField.setAccessible(true);
+ player = (Player) playerField.get(event);
+ }
+ }
+
+ if (player != null) {
+ setSenderContext(player);
+ }
+ } catch (Exception ignored) {
+ } // We can't really safely log exceptions.
+
+ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event)));
+ }
+
+ public static void removeEventContext() {
+ removePluginContext();
+ removeSenderContext();
+ ThreadContext.remove("pufferfishsentry_eventdata");
+ }
+
+ private static Map<String, String> serializeFields(Object object) {
+ Map<String, String> fields = new TreeMap<>();
+ fields.put("_class", object.getClass().getName());
+ for (Field declaredField : object.getClass().getDeclaredFields()) {
+ try {
+ if (Modifier.isStatic(declaredField.getModifiers())) {
+ continue;
+ }
+
+ String fieldName = declaredField.getName();
+ if (fieldName.equals("handlers")) {
+ continue;
+ }
+ declaredField.setAccessible(true);
+ Object value = declaredField.get(object);
+ if (value != null) {
+ fields.put(fieldName, value.toString());
+ } else {
+ fields.put(fieldName, "<null>");
+ }
+ } catch (Exception ignored) {
+ } // We can't really safely log exceptions.
+ }
+ return fields;
+ }
+
+ public static class State {
+
+ private Plugin plugin;
+ private Command command;
+ private String commandLine;
+ private Event event;
+ private RegisteredListener registeredListener;
+
+ public Plugin getPlugin() {
+ return plugin;
+ }
+
+ public void setPlugin(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
+ public Command getCommand() {
+ return command;
+ }
+
+ public void setCommand(Command command) {
+ this.command = command;
+ }
+
+ public String getCommandLine() {
+ return commandLine;
+ }
+
+ public void setCommandLine(String commandLine) {
+ this.commandLine = commandLine;
+ }
+
+ public Event getEvent() {
+ return event;
+ }
+
+ public void setEvent(Event event) {
+ this.event = event;
+ }
+
+ public RegisteredListener getRegisteredListener() {
+ return registeredListener;
+ }
+
+ public void setRegisteredListener(RegisteredListener registeredListener) {
+ this.registeredListener = registeredListener;
+ }
+ }
+}
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
index ab36e3aaff57e2f27b5aed06b4bdfe277f86a35e..96da9f1082ab134d197b3a6069f2fcdf38585efe 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
@@ -597,7 +597,9 @@ public final class SimplePluginManager implements PluginManager {
// Paper start
private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, msg, ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));
}
// Paper end
@@ -667,9 +669,11 @@ public final class SimplePluginManager implements PluginManager {
));
}
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish
// Paper start - error reporting
String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
server.getLogger().log(Level.SEVERE, msg, ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish
if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event)));
}
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index b412aaf08901d169ac9fc89b36f9d6ccb95c53d3..45a9ca8969f635d20cc44c062fda85bbccd8f8ff 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -336,7 +336,13 @@ public final class JavaPluginLoader implements PluginLoader {
try {
jPlugin.setEnabled(true);
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
+ // Paper start - Disable plugins that fail to load
+ this.server.getPluginManager().disablePlugin(jPlugin);
+ return;
+ // Paper end
}
// Perhaps abort here, rather than continue going, but as it stands,
@@ -361,7 +367,9 @@ public final class JavaPluginLoader implements PluginLoader {
try {
jPlugin.setEnabled(false);
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
}
if (cloader instanceof PluginClassLoader) {

View File

@@ -192,10 +192,10 @@ index 0000000000000000000000000000000000000000..9f6896711907ac30fe0c00130207b970
+}
diff --git a/src/main/java/me/earthme/luminol/config/LuminolConfig.java b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..fcacd381e4a5875ed0c542a9e6c1804fae823435
index 0000000000000000000000000000000000000000..526b68e184a2f6f9e38cd02995b473a943404141
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
@@ -0,0 +1,221 @@
@@ -0,0 +1,226 @@
+package me.earthme.luminol.config;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
@@ -238,7 +238,8 @@ index 0000000000000000000000000000000000000000..fcacd381e4a5875ed0c542a9e6c1804f
+
+ dropAllInstanced();
+ try {
+ loadConfig();
+ preLoadConfig();
+ finalizeLoadConfig();
+ }catch (Exception e){
+ logger.error(e);
+ }
@@ -259,7 +260,13 @@ index 0000000000000000000000000000000000000000..fcacd381e4a5875ed0c542a9e6c1804f
+ allInstanced.clear();
+ }
+
+ public static void loadConfig() throws IOException {
+ public static void finalizeLoadConfig() {
+ for (IConfigModule module : allInstanced) {
+ module.onLoaded(configFileInstance);
+ }
+ }
+
+ public static void preLoadConfig() throws IOException {
+ baseConfigFolder.mkdirs();
+
+ if (!baseConfigFile.exists()){
@@ -334,8 +341,6 @@ index 0000000000000000000000000000000000000000..fcacd381e4a5875ed0c542a9e6c1804f
+ field.set(null,actuallyValue);
+ }
+ }
+
+ singleConfigModule.onLoaded(configFileInstance);
+ }
+
+ public static @NotNull Set<Class<?>> getClasses(String pack) {
@@ -576,15 +581,27 @@ index 0000000000000000000000000000000000000000..de94c8e39f0ae0da80d5a79af63413e2
+ // Paper end - lifecycle events
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 300a044bb0f0e377133f24469cea1a9669de6e58..b30690eba7f06e5af06fb3019e89c067629b77a6 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -123,6 +123,7 @@ public class Main {
}
io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper
+ me.earthme.luminol.config.LuminolConfig.preLoadConfig(); //Luminol - load config file
Bootstrap.bootStrap();
Bootstrap.validate();
Util.startTimerHackThread();
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 78f33298e809a7f6d079d9f2c64e2caa47a1b25a..e3c8deea68ef49bcd07359e243a12afb57cbcf52 100644
index 78f33298e809a7f6d079d9f2c64e2caa47a1b25a..426efbc58deb56e044a6b51021ea63cd8f120a14 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -223,6 +223,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
// Paper end - initialize global and world-defaults configuration
+ me.earthme.luminol.config.LuminolConfig.loadConfig(); //Luminol - load config file
+ me.earthme.luminol.config.LuminolConfig.finalizeLoadConfig(); //Luminol - load config file
+ me.earthme.luminol.config.LuminolConfig.setupLatch(); //Luminol - load config file
this.server.spark.enableEarlyIfRequested(); // Paper - spark
// Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save

View File

@@ -6,10 +6,10 @@ Subject: [PATCH] Add config for unsafe teleportation
diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea374875f529b30db17e8b8cb07b99a600b722dc
index 0000000000000000000000000000000000000000..865ffe0051d84ac9018ab54a54894c2fe8fd573e
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/UnsafeTeleportationConfig.java
@@ -0,0 +1,20 @@
@@ -0,0 +1,22 @@
+package me.earthme.luminol.config.modules.fixes;
+
+import me.earthme.luminol.config.ConfigInfo;
@@ -17,7 +17,9 @@ index 0000000000000000000000000000000000000000..ea374875f529b30db17e8b8cb07b99a6
+import me.earthme.luminol.config.IConfigModule;
+
+public class UnsafeTeleportationConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled", comments = "Allow non player entities enter end portals if enabled.If you want to use sand duping,please turn on this")
+ @ConfigInfo(baseName = "enabled", comments = "Allow non player entities enter end portals if enabled.\n" +
+ "If you want to use sand duping,please turn on this.\n" +
+ "Warning: This would cause some unsafe issues, you could learn more on : https://github.com/PaperMC/Folia/issues/297")
+ public static boolean enabled = false;
+
+ @Override

View File

@@ -4,21 +4,6 @@ Date: Wed, 7 Feb 2024 04:50:10 +0000
Subject: [PATCH] Add config for username check
diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
index 8849862b45ccbbc635a1c316e9870bca81e55c04..774521cf327592adeef67f3fb8f6334e0b7de799 100644
--- a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java
@@ -294,8 +294,8 @@ public class CraftPlayerProfile implements PlayerProfile, SharedPlayerProfile {
}
private static GameProfile createAuthLibProfile(UUID uniqueId, String name) {
- Preconditions.checkArgument(name == null || name.length() <= 16, "Name cannot be longer than 16 characters");
- Preconditions.checkArgument(name == null || StringUtil.isValidPlayerName(name), "The name of the profile contains invalid characters: %s", name);
+ Preconditions.checkArgument(name == null || name.length() <= 16 || !me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled, "Name cannot be longer than 16 characters");
+ Preconditions.checkArgument(name == null || StringUtil.isValidPlayerName(name) || !me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled, "The name of the profile contains invalid characters: %s", name);
return new GameProfile(
uniqueId != null ? uniqueId : Util.NIL_UUID,
name != null ? name : ""
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/UsernameCheckConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7e4724cc4ab8d911bcaf0106c098b266c843bb1
@@ -46,7 +31,7 @@ index 0000000000000000000000000000000000000000..c7e4724cc4ab8d911bcaf0106c098b26
+ }
+}
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index 227d62a69a453d49c28568ecb41ecef85a35405b..d1f70437eb43dd536e7b3dac7a770525eff55318 100644
index 227d62a69a453d49c28568ecb41ecef85a35405b..8951397adcc5505304d0dece6435aab786017399 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -178,7 +178,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
@@ -54,30 +39,39 @@ index 227d62a69a453d49c28568ecb41ecef85a35405b..d1f70437eb43dd536e7b3dac7a770525
Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
// Paper start - Validate usernames
- if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled //Luminol - Add config for username check
+ if (me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled // Luminol - Add config for username check
+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()
&& io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation
&& !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) {
Validate.validState(StringUtil.isReasonablePlayerName(packet.name()), "Invalid characters in username", new Object[0]);
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
index f58dec12326734c61f4bc2298a87fb38f1ac1dc4..249ecfb1b1830befa43ba172c65527b077bb8f4e 100644
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
@@ -42,7 +42,7 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
Preconditions.checkArgument(isValidSkullProfile, "The skull profile is missing a name or textures!");
// Paper start - Validate
Preconditions.checkArgument(gameProfile.getName().length() <= 16, "The name of the profile is longer than 16 characters");
- Preconditions.checkArgument(net.minecraft.util.StringUtil.isValidPlayerName(gameProfile.getName()), "The name of the profile contains invalid characters: %s", gameProfile.getName());
+ Preconditions.checkArgument(!me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled || net.minecraft.util.StringUtil.isValidPlayerName(gameProfile.getName()), "The name of the profile contains invalid characters: %s", gameProfile.getName()); // Luminol - Add config for username checks
final PropertyMap properties = gameProfile.getProperties();
Preconditions.checkArgument(properties.size() <= 16, "The profile contains more than 16 properties");
for (final Property property : properties.values()) {
@@ -79,7 +79,7 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
Preconditions.checkArgument((uniqueId != null) || !StringUtils.isBlank(name), "uniqueId is null or name is blank");
}
Preconditions.checkArgument(name == null || name.length() <= 16, "The name of the profile is longer than 16 characters"); // Paper - Validate
- Preconditions.checkArgument(name == null || net.minecraft.util.StringUtil.isValidPlayerName(name), "The name of the profile contains invalid characters: %s", name); // Paper - Validate
+ Preconditions.checkArgument(!me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled || name == null || net.minecraft.util.StringUtil.isValidPlayerName(name), "The name of the profile contains invalid characters: %s", name); // Paper - Validate // Luminol - Add config for username checks
this.uniqueId = uniqueId;
this.name = name;
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
index 34b4166adfae8ff7d1eb73d56a72931b005330a7..fc95632268caa8941dcce7a575ce00303864c4c1 100644
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -82,7 +82,7 @@ public class GameProfileCache {
}
private static Optional<GameProfile> lookupGameProfile(GameProfileRepository repository, String name) {
- if (!StringUtil.isValidPlayerName(name)) {
+ if (!StringUtil.isValidPlayerName(name, false)) { // Luminol - Add config for username check - Directly return, skip unnecessary following logic
return GameProfileCache.createUnknownProfile(name);
} else {
final AtomicReference<GameProfile> atomicreference = new AtomicReference();
diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java
index 6c33002dc8bbb3759c3156302ab7d1f26ce5e8ee..8caf8dd187dfdc67a8b97db080a9fe0ef5234943 100644
--- a/src/main/java/net/minecraft/util/StringUtil.java
+++ b/src/main/java/net/minecraft/util/StringUtil.java
@@ -64,6 +64,13 @@ public class StringUtil {
}
public static boolean isValidPlayerName(String name) {
+ // Luminol start - Add config for username check
+ return isValidPlayerName(name, !me.earthme.luminol.config.modules.misc.UsernameCheckConfig.enabled);
+ }
+
+ public static boolean isValidPlayerName(String name, boolean bypassCheck) {
+ if (bypassCheck) return name.length() <= 16;
+ // Luminol end - Add config for username check
return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
}

View File

@@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
Date: Tue, 24 Dec 2024 13:28:56 -0500
Subject: [PATCH] Add config for tripwire dupe
Bring back MC-59471, MC-129055 on 1.21.2+, which fixed in 1.21.2 snapshots 24w33a and 24w36a
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..8def8aad908f5e6b828d7d9179bfe1962c39f9f7
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/TripwireConfig.java
@@ -0,0 +1,20 @@
+package me.earthme.luminol.config.modules.misc;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class TripwireConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "tripwire_dupe";
+ }
+}
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
index c2589f42c467ca672417c24076313da51bb2dcbb..f85f53082cf5a56c723648f68bb103d58da0e8bd 100644
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -206,7 +206,7 @@ public class TripWireHookBlock extends Block {
if (iblockdata4 != null) {
BlockState iblockdata5 = world.getBlockState(blockposition2);
- if (iblockdata5.is(Blocks.TRIPWIRE) || iblockdata5.is(Blocks.TRIPWIRE_HOOK)) {
+ if (me.earthme.luminol.config.modules.misc.TripwireConfig.enabled || iblockdata5.is(Blocks.TRIPWIRE) || iblockdata5.is(Blocks.TRIPWIRE_HOOK)) { // Luminol - Add config for tripwire dupe
world.setBlock(blockposition2, (BlockState) iblockdata4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3);
}
}

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 15 Dec 2024 12:53:33 +0800
Subject: [PATCH] Add configurable region format framework & linear v2 region
Subject: [PATCH] Add configurable region format framework & linear v2 region
format support
@@ -68,24 +68,19 @@ index 0000000000000000000000000000000000000000..d92f1d549c7e01daa6b5bba7d405e462
+}
diff --git a/src/main/java/abomination/LinearRegionFile.java b/src/main/java/abomination/LinearRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c96f6173e
index 0000000000000000000000000000000000000000..bb0fcf5f47b5ae3d86e1d0572f951236afdcd017
--- /dev/null
+++ b/src/main/java/abomination/LinearRegionFile.java
@@ -0,0 +1,666 @@
@@ -0,0 +1,622 @@
+package abomination;
+
+import ca.spottedleaf.concurrentutil.executor.PrioritisedExecutor;
+import ca.spottedleaf.concurrentutil.executor.thread.PrioritisedThreadPool;
+import ca.spottedleaf.concurrentutil.util.Priority;
+import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
+import com.github.luben.zstd.ZstdInputStream;
+import com.github.luben.zstd.ZstdOutputStream;
+import com.mojang.logging.LogUtils;
+import me.earthme.luminol.config.modules.misc.RegionFormatConfig;
+import net.jpountz.lz4.LZ4Compressor;
+import net.jpountz.lz4.LZ4Factory;
+import net.jpountz.lz4.LZ4FastDecompressor;
+import net.minecraft.server.MinecraftServer;
+import net.openhft.hashing.LongHashFunction;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
@@ -99,12 +94,12 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.IntStream;
+
+// LinearRegionFile_implementation_version_0_5byXymb
+// Just gonna use this string to inform other forks about updates ;-)
@@ -134,9 +129,7 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ private final int compressionLevel;
+ private int gridSize = 8;
+ private int bucketSize = 4;
+
+ private final AtomicInteger modifiedChunkCount = new AtomicInteger(0);
+ private PrioritisedExecutor.PrioritisedTask ioTask = null;
+ private final Thread bindThread;
+
+ public Path getRegionFile() {
+ return this.regionFile;
@@ -206,7 +199,7 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ File regionFile = new File(this.regionFile.toString());
+
+ if(!regionFile.canRead()) {
+ //this.start();
+ this.bindThread.start();
+ return;
+ }
+
@@ -227,7 +220,7 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ throw new RuntimeException("Invalid version: " + version + " file " + this.regionFile);
+ }
+
+ //this.start();
+ this.bindThread.start();
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to open region file " + this.regionFile, e);
+ }
@@ -331,6 +324,35 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ }
+
+ public LinearRegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync, int compressionLevel) throws IOException {
+ Runnable flushCheck = () -> {
+ while (!close) {
+ synchronized (saveLock) {
+ if (markedToSave && activeSaveThreads < SAVE_THREAD_MAX_COUNT) {
+ activeSaveThreads++;
+ Runnable flushOperation = () -> {
+ try {
+ flush();
+ } catch (IOException ex) {
+ LOGGER.error("Region file {} flush failed", this.regionFile.toAbsolutePath(), ex);
+ } finally {
+ synchronized (saveLock) {
+ activeSaveThreads--;
+ }
+ }
+ };
+
+ Thread saveThread = USE_VIRTUAL_THREAD ?
+ Thread.ofVirtual().name("Linear IO - " + LinearRegionFile.this.hashCode()).unstarted(flushOperation) :
+ Thread.ofPlatform().name("Linear IO - " + LinearRegionFile.this.hashCode()).unstarted(flushOperation);
+ saveThread.setPriority(Thread.NORM_PRIORITY - 3);
+ saveThread.start();
+ }
+ }
+ LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(SAVE_DELAY_MS));
+ }
+ };
+ this.bindThread = USE_VIRTUAL_THREAD ? Thread.ofVirtual().unstarted(flushCheck) : Thread.ofPlatform().unstarted(flushCheck);
+ this.bindThread.setName("Linear IO Schedule - " + this.hashCode());
+ this.regionFile = path;
+ this.compressionLevel = compressionLevel;
+
@@ -354,52 +376,34 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ }
+ }
+
+ private static final AtomicInteger ioThreadId = new AtomicInteger();
+ private static final PrioritisedThreadPool linearIOThreadPool = new PrioritisedThreadPool(thread -> {
+ thread.setName("Linear RegionFile IO Thread- " + ioThreadId.getAndIncrement());
+ thread.setContextClassLoader(MinecraftServer.class.getClassLoader());
+ });
+ public static final long WORKER_QUEUE_HOLD_TIME = (long)(20.0e6); // 20ms
+ private static PrioritisedExecutor linearIOExecutor;
+
+ /*
+ private static final int SAVE_THREAD_MAX_COUNT = 6;
+ public static int SAVE_THREAD_MAX_COUNT = 6;
+ public static int SAVE_DELAY_MS = 100;
+ public static boolean USE_VIRTUAL_THREAD = true;
+ private static final Object saveLock = new Object();
+ private static int activeSaveThreads = 0;
+ */
+
+ public static void initIOExecutor() {
+ linearIOExecutor = linearIOThreadPool.createExecutorGroup(1, 0).createExecutor(RegionFormatConfig.linearIoThreadCount, WORKER_QUEUE_HOLD_TIME, 0);
+ }
+
+ public static void shutdownIOExecutor() {
+ linearIOThreadPool.shutdown(true);
+ }
+
+ /*public void run() {
+ try {
+ while (!close) {
+ synchronized (saveLock) {
+ if (markedToSave && activeSaveThreads < SAVE_THREAD_MAX_COUNT) {
+ activeSaveThreads++;
+ Thread saveThread = new Thread(() -> {
+ try {
+ flush();
+ } catch (IOException ex) {
+ LOGGER.error("Region file " + this.regionFile.toAbsolutePath() + " flush failed", ex);
+ } finally {
+ synchronized (saveLock) {
+ activeSaveThreads--;
+ }
+ while (!close) {
+ synchronized (saveLock) {
+ if (markedToSave && activeSaveThreads < SAVE_THREAD_MAX_COUNT) {
+ activeSaveThreads++;
+ Thread saveThread = new Thread(() -> {
+ try {
+ flush();
+ } catch (IOException ex) {
+ LOGGER.error("Region file " + this.regionFile.toAbsolutePath() + " flush failed", ex);
+ } finally {
+ synchronized (saveLock) {
+ activeSaveThreads--;
+ }
+ }, "RegionFileFlush");
+ saveThread.setPriority(Thread.NORM_PRIORITY - 3);
+ saveThread.start();
+ }
+ }
+ }, "RegionFileFlush");
+ saveThread.setPriority(Thread.NORM_PRIORITY - 3);
+ saveThread.start();
+ }
+ Thread.sleep(100);
+ }
+ } catch(InterruptedException ignored) {}
+ LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(SAVE_DELAY_MS));
+ }
+ }*/
+
+ public synchronized boolean doesChunkExist(ChunkPos pos) throws Exception {
@@ -414,7 +418,7 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+
+ long timestamp = getTimestamp();
+
+ long writeStart = System.nanoTime();
+long writeStart = System.nanoTime();
+ File tempFile = new File(regionFile.toString() + ".tmp");
+ FileOutputStream fileStream = new FileOutputStream(tempFile);
+ DataOutputStream dataStream = new DataOutputStream(fileStream);
@@ -515,7 +519,6 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ fileStream.close();
+ Files.move(tempFile.toPath(), this.regionFile, StandardCopyOption.REPLACE_EXISTING);
+//System.out.println("writeStart REGION FILE FLUSH " + (System.nanoTime() - writeStart) + " misses: " + bucketMisses);
+ this.modifiedChunkCount.set(0);
+ }
+
+ private void writeNBTFeatures(DataOutputStream dataStream) throws IOException {
@@ -558,53 +561,6 @@ index 0000000000000000000000000000000000000000..4a8a71686dddfc6b0c27882d1f73b92c
+ LOGGER.error("Chunk write IOException " + e + " " + this.regionFile);
+ }
+ markToSave();
+ this.modifiedChunkCount.getAndIncrement();
+
+ if (ioTask == null) {
+ this.scheduleSave();
+ }else {
+ if (this.ioTask.getPriority() == Priority.COMPLETING) {
+ this.scheduleSave();
+ return;
+ }
+
+ this.ioTask.raisePriority(this.computeSavePriority());
+ }
+ }
+
+ private Priority computeSavePriority() {
+ final int currentModifiedChunkCount = this.modifiedChunkCount.get();
+
+ final int[] ordinals = new int[]{2, 3, 4, 5, 6};
+ final int[] thresholds = new int[]{20, 40, 60, 80, 100};
+ final int coverPercent = (currentModifiedChunkCount / 1024) * 100;
+
+ int actualOrdinal = 6;
+ for (int i = 0; i < thresholds.length; i++) {
+ if (coverPercent >= thresholds[i]) {
+ actualOrdinal = ordinals[i];
+ }
+ }
+
+ return Priority.values()[actualOrdinal];
+ }
+
+ private void scheduleSave() {
+ final PrioritisedExecutor.PrioritisedTask created = linearIOExecutor.createTask(() -> {
+ try {
+ synchronized (this) {
+ if (!this.close) {
+ this.flush();
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }, this.computeSavePriority());
+
+ created.queue();
+
+ this.ioTask = created;
+ }
+
+ public DataOutputStream getChunkDataOutputStream(ChunkPos pos) {
@@ -763,7 +719,7 @@ index 1acea58838f057ab87efd103cbecb6f5aeaef393..f9b89684208b9fe2c93f0368f7df5a40
public static interface IORunnable {
- public void run(final RegionFile regionFile) throws IOException;
+ public void run(final abomination.IRegionFile regionFile) throws IOException;
+ public void run(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
}
}
@@ -780,28 +736,34 @@ index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d
}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..60546260cd1d535cc596485de2ced48b7e045b3a
index 0000000000000000000000000000000000000000..eb689b6b79143ffaf1eadcba84feca0c632d1407
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
@@ -0,0 +1,48 @@
@@ -0,0 +1,59 @@
+package me.earthme.luminol.config.modules.misc;
+
+import abomination.LinearRegionFile;
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.DoNotLoad;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.*;
+import me.earthme.luminol.utils.EnumRegionFormat;
+import net.minecraft.server.MinecraftServer;
+
+public class RegionFormatConfig implements IConfigModule {
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "format")
+ public static String format = "MCA";
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_compression_level")
+ public static int linearCompressionLevel = 1;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_io_thread_count")
+ public static int linearIoThreadCount = 6;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_io_flush_delay_ms")
+ public static int linearIoFlushDelayMs = 100;
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_use_virtual_thread")
+ public static boolean linearUseVirtualThread = true;
+
+ @DoNotLoad
+ public static EnumRegionFormat regionFormat;
@@ -818,17 +780,22 @@ index 0000000000000000000000000000000000000000..60546260cd1d535cc596485de2ced48b
+
+ @Override
+ public void onLoaded(CommentedFileConfig configInstance) {
+ LinearRegionFile.initIOExecutor();
+ regionFormat = EnumRegionFormat.fromString(format.toUpperCase());
+
+ if (regionFormat == null) {
+ throw new RuntimeException("Invalid region format: " + format);
+ }
+
+ if (RegionFormatConfig.linearCompressionLevel > 23 || RegionFormatConfig.linearCompressionLevel < 1) {
+ MinecraftServer.LOGGER.error("Linear region compression level should be between 1 and 22 in config: {}", RegionFormatConfig.linearCompressionLevel);
+ MinecraftServer.LOGGER.error("Falling back to compression level 1.");
+ RegionFormatConfig.linearCompressionLevel = 1;
+ if (regionFormat == EnumRegionFormat.LINEAR_V2) {
+ if (RegionFormatConfig.linearCompressionLevel > 23 || RegionFormatConfig.linearCompressionLevel < 1) {
+ MinecraftServer.LOGGER.error("Linear region compression level should be between 1 and 22 in config: {}", RegionFormatConfig.linearCompressionLevel);
+ MinecraftServer.LOGGER.error("Falling back to compression level 1.");
+ RegionFormatConfig.linearCompressionLevel = 1;
+ }
+
+ LinearRegionFile.SAVE_DELAY_MS = linearIoFlushDelayMs;
+ LinearRegionFile.SAVE_THREAD_MAX_COUNT = linearIoThreadCount;
+ LinearRegionFile.USE_VIRTUAL_THREAD = linearUseVirtualThread;
+ }
+ }
+}
@@ -907,17 +874,22 @@ index 0000000000000000000000000000000000000000..5af068489646ed70330d8c6242ec88f5
+
+public record RegionCreatorInfo (RegionStorageInfo info, Path filePath, Path folder, boolean sync) {}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 8cc0c01a19fc71753d7c3ed4fa7e9992aaf93b5a..88be8a6232bc3311cc0bdb7c697f7a78ce33e38d 100644
index 8cc0c01a19fc71753d7c3ed4fa7e9992aaf93b5a..04f68856cb3d982f1644d26f5ae57587b6e36ff2 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1180,6 +1180,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.saveAllChunks(false, true, true, true); // Paper - rewrite chunk system
@@ -1036,10 +1036,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
while (iterator1.hasNext()) {
ServerLevel worldserver2 = (ServerLevel) iterator1.next();
this.isSaving = false;
+ abomination.LinearRegionFile.shutdownIOExecutor(); // Luminol - Linear region file format
// Folia start - region threading
this.stopPart2();
}
- MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", worldserver2.getChunkSource().chunkMap.getStorageName());
+ MinecraftServer.LOGGER.info("ThreadedChunkStorage ({}): All chunks are saved", worldserver2.getChunkSource().chunkMap.getStorageName()); // Luminol - configurable region format
}
- MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved");
+ MinecraftServer.LOGGER.info("ThreadedChunkStorage: All dimensions are saved"); // Luminol - configurable region format
}
return flag3;
diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
index 622d0cbe023774d92d212f242b60b96317720835..9b4b01a741e8779f4ea06b0fd801ce243e179910 100644
--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
@@ -945,7 +917,7 @@ index 622d0cbe023774d92d212f242b60b96317720835..9b4b01a741e8779f4ea06b0fd801ce24
try {
- RegionFile regionfile = new RegionFile(key, file.toPath(), regionDirectory, true);
+ abomination.IRegionFile regionfile = net.minecraft.world.level.chunk.storage.RegionFileStorage.createNew(key, file.toPath(), regionDirectory, true);
+ abomination.IRegionFile regionfile = net.minecraft.world.level.chunk.storage.RegionFileStorage.createNew(key, file.toPath(), regionDirectory, true); // Luminol - Configurable region file format
try {
for (int i1 = 0; i1 < 32; ++i1) {
@@ -954,7 +926,7 @@ index 622d0cbe023774d92d212f242b60b96317720835..9b4b01a741e8779f4ea06b0fd801ce24
protected abstract boolean tryProcessOnePosition(T storage, ChunkPos chunkPos, ResourceKey<Level> worldKey);
- private void onFileFinished(RegionFile regionFile) {
+ private void onFileFinished(abomination.IRegionFile regionFile) {
+ private void onFileFinished(abomination.IRegionFile regionFile) { // Luminol - Configurable region file format
if (WorldUpgrader.this.recreateRegionFiles) {
if (this.previousWriteFuture != null) {
this.previousWriteFuture.join();
@@ -963,7 +935,7 @@ index 622d0cbe023774d92d212f242b60b96317720835..9b4b01a741e8779f4ea06b0fd801ce24
}
- static record FileToUpgrade(RegionFile file, List<ChunkPos> chunksToUpgrade) {
+ static record FileToUpgrade(abomination.IRegionFile file, List<ChunkPos> chunksToUpgrade) {
+ static record FileToUpgrade(abomination.IRegionFile file, List<ChunkPos> chunksToUpgrade) { // Luminol - Configurable region file format
}
@@ -1030,7 +1002,7 @@ index 16f07007a0f73ec0c6f421c9b082518e87e8cc7b..fc69834e18e0860750d878e1361722fc
}
// Paper end - rewrite chunk system
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a166e42cf 100644
index e40665cead218502b44dd49051a53326ed94f061..a25e1bfd74b7ec9d6fcc3fe7c4369bc20b33a0da 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -23,7 +23,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -1042,7 +1014,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
private final RegionStorageInfo info;
private final Path folder;
private final boolean sync;
@@ -33,8 +33,28 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -33,8 +33,27 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
private static final int MAX_NON_EXISTING_CACHE = 1024 * 4;
private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
private static String getRegionFileName(final int chunkX, final int chunkZ) {
@@ -1055,9 +1027,8 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
+ final String fullFileName = filePath.getFileName().toString();
+ final String[] fullNameSplit = fullFileName.split("\\.");
+ final String extensionName = fullNameSplit[fullNameSplit.length - 1];
+ final String expectedExtensionName = "." + regionFormat.getArgument();
+
+ if (!expectedExtensionName.equalsIgnoreCase(extensionName)) {
+ if (!regionFormat.getArgument().equalsIgnoreCase(extensionName)) {
+ net.minecraft.server.MinecraftServer.setFatalException(new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument()));
+ throw new IOException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
+ }
@@ -1072,7 +1043,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
private boolean doesRegionFilePossiblyExist(final long position) {
synchronized (this.nonExistingRegionFiles) {
@@ -68,15 +88,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -68,15 +87,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
}
@Override
@@ -1091,7 +1062,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
if (ret != null) {
return ret;
}
@@ -100,7 +120,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -100,7 +119,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
FileUtil.createDirectoriesSafe(this.folder);
@@ -1100,7 +1071,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
this.regionCache.putAndMoveToFirst(key, ret);
@@ -119,7 +139,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -119,7 +138,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
}
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
@@ -1109,7 +1080,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
// note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
// (and, the regionfile parameter is unused for writing until the write call)
@@ -153,7 +173,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -153,7 +172,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
) throws IOException {
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
@@ -1118,7 +1089,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
if (regionFile != null) {
regionFile.clear(pos);
} // else: didn't exist
@@ -168,7 +188,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -168,7 +187,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.ReadData moonrise$readData(
final int chunkX, final int chunkZ
) throws IOException {
@@ -1127,7 +1098,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
@@ -221,7 +241,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -221,7 +240,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@Nullable
public static ChunkPos getRegionFileCoordinates(Path file) {
String fileName = file.getFileName().toString();
@@ -1136,7 +1107,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
return null;
}
@@ -250,12 +270,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -250,12 +269,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
}
// Paper start - rewrite chunk system
@@ -1151,7 +1122,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
// Paper start - rewrite chunk system
if (existingOnly) {
return this.moonrise$getRegionFileIfExists(chunkcoordintpair.x, chunkcoordintpair.z);
@@ -263,7 +283,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -263,7 +282,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
synchronized (this) {
final long key = ChunkPos.asLong(chunkcoordintpair.x >> REGION_SHIFT, chunkcoordintpair.z >> REGION_SHIFT);
@@ -1160,16 +1131,16 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
if (ret != null) {
return ret;
}
@@ -278,7 +298,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -278,7 +297,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
FileUtil.createDirectoriesSafe(this.folder);
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync);
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
this.regionCache.putAndMoveToFirst(key, ret);
@@ -292,7 +312,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -292,7 +311,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
}
@@ -1178,7 +1149,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
synchronized (regionfile) {
try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
@@ -327,7 +347,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -327,7 +346,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@Nullable
public CompoundTag read(ChunkPos pos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -1187,7 +1158,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
if (regionfile == null) {
return null;
}
@@ -391,7 +411,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -391,7 +410,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
public void scanChunk(ChunkPos chunkPos, StreamTagVisitor scanner) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -1196,7 +1167,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
if (regionfile == null) {
return;
}
@@ -421,7 +441,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -421,7 +440,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
}
public void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { // Paper - rewrite chunk system - public
@@ -1205,7 +1176,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
// Paper start - rewrite chunk system
if (regionfile == null) {
// if the RegionFile doesn't exist, no point in deleting from it
@@ -465,7 +485,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -465,7 +484,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
// Paper start - rewrite chunk system
synchronized (this) {
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
@@ -1214,7 +1185,7 @@ index e40665cead218502b44dd49051a53326ed94f061..a3823a73758a5cb659aca299157e954a
try {
regionFile.close();
} catch (final IOException ex) {
@@ -482,7 +502,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -482,7 +501,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
// Paper start - rewrite chunk system
synchronized (this) {
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Tue, 31 Dec 2024 17:45:55 +0800
Subject: [PATCH] Add config for watchdog timeout
diff --git a/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java b/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
index 258d82ab2c78482e1561343e8e1f81fc33f1895e..967107c0f4a18a29877883ccddb4d7962f4b5788 100644
--- a/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
+++ b/src/main/java/io/papermc/paper/threadedregions/FoliaWatchdogThread.java
@@ -65,7 +65,7 @@ public final class FoliaWatchdogThread extends Thread {
for (final RunningTick tick : ticks) {
final long elapsed = now - tick.lastPrint;
- if (elapsed <= TimeUnit.SECONDS.toNanos(5L)) {
+ if (elapsed <= TimeUnit.MILLISECONDS.toNanos(me.earthme.luminol.config.modules.misc.FoliaWatchogConfig.tickRegionTimeOutMs)) { // Luminol - Add config for watchdog timeout
continue;
}
tick.lastPrint = now;
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/FoliaWatchogConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/FoliaWatchogConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..de58b5bf9dedf35bc56a9211d0769b988704a7fe
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/FoliaWatchogConfig.java
@@ -0,0 +1,20 @@
+package me.earthme.luminol.config.modules.misc;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class FoliaWatchogConfig implements IConfigModule {
+ @ConfigInfo(baseName = "tick_region_time_out_ms")
+ public static int tickRegionTimeOutMs = 5000;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "folia_watchdog";
+ }
+}

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sat, 11 Jan 2025 15:23:31 +0800
Subject: [PATCH] Try fixing folia #315
Might be useful to https://github.com/PaperMC/Folia/issues/315
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
index 3bd0f3ae53eaa22409152d7f41e511e76bdaa265..6e76e4801653d0c84cb811bf72f1e1e8e1712ff6 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
@@ -51,7 +51,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
return Items.ENDER_PEARL;
}
- @Override
+ /*@Override // Luminol - Try fixing folia #315
protected void setOwnerThroughUUID(UUID uuid) {
this.deregisterFromCurrentOwner();
super.setOwnerThroughUUID(uuid);
@@ -64,6 +64,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
super.setOwner(entity);
this.registerToCurrentOwner();
}
+ */ // Luminol - Try fixing folia #315
private void deregisterFromCurrentOwner() {
Entity entity = this.getOwner();
@@ -388,7 +389,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
@Override
public void onRemoval(Entity.RemovalReason reason) {
if (reason != Entity.RemovalReason.UNLOADED_WITH_PLAYER) {
- this.deregisterFromCurrentOwner();
+ // this.deregisterFromCurrentOwner(); // Luminol - Try fixing folia #315
}
super.onRemoval(reason);

View File

@@ -18,7 +18,7 @@ index 48604e7f96adc9e226e034054c5e2bad0b024eb5..99f0c1e4d3437154a1062b0a8f94b7a0
return;
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f27943174f718d0 100644
index 04f68856cb3d982f1644d26f5ae57587b6e36ff2..55bac6e6cccce6e0282936ac78bbe82628daa655 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -809,8 +809,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -41,7 +41,7 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
this.server.disablePlugins();
this.server.waitForAsyncTasksShutdown(); // Paper - Wait for Async Tasks during shutdown
}
@@ -1324,7 +1324,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1323,7 +1323,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.statusIcon = (ServerStatus.Favicon) this.loadStatusIcon().orElse(null); // CraftBukkit - decompile error
this.status = this.buildServerStatus();
@@ -50,7 +50,7 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
// Folia start - region threading
if (true) {
io.papermc.paper.threadedregions.RegionizedServer.getInstance().init(); // Folia - region threading - only after loading worlds
@@ -1729,7 +1729,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1728,7 +1728,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
if (this.emptyTicks >= j) {
@@ -59,7 +59,7 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
if (this.emptyTicks == j) {
MinecraftServer.LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhileEmptySeconds());
this.autoSave();
@@ -1748,7 +1748,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1747,7 +1747,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end - avoid issues with certain tasks not processing during sleep
// Folia - region threading
this.tickConnection();
@@ -69,7 +69,7 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
return;
}
}
@@ -1773,7 +1774,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1772,7 +1773,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
};
// Folia end - region threading
@@ -78,7 +78,7 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
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) {
@@ -1844,7 +1845,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1843,7 +1844,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
@@ -88,12 +88,12 @@ index 88be8a6232bc3311cc0bdb7c697f7a78ce33e38d..c7390e0341cd19fa5e0b21882f279431
// Folia - region threading
gameprofilerfiller.pop();
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 295504dab771c8bb8c668545fe5d62eae0561b76..49b4ef6457743b5f955bff70694378d4975e44a7 100644
index e6db178f57b63a1abb72c965d4a6e67f97d3b570..3c26533876ffa1d06bbc4d68f2712b8c96e37351 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -225,7 +225,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
// Paper end - initialize global and world-defaults configuration
me.earthme.luminol.config.LuminolConfig.loadConfig(); //Luminol - load config file
me.earthme.luminol.config.LuminolConfig.finalizeLoadConfig(); //Luminol - load config file
me.earthme.luminol.config.LuminolConfig.setupLatch(); //Luminol - load config file
- this.server.spark.enableEarlyIfRequested(); // Paper - spark
+ if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark

View File

@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Wed, 1 Jan 2025 12:18:18 +0800
Subject: [PATCH] Set old pos before moving entity by piston
diff --git a/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPistonIssueFixConfig.java b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPistonIssueFixConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..6edfb1d36a88d319151d28ba14873269736f84b6
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/fixes/FoliaPistonIssueFixConfig.java
@@ -0,0 +1,20 @@
+package me.earthme.luminol.config.modules.fixes;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+
+public class FoliaPistonIssueFixConfig implements IConfigModule {
+ @ConfigInfo(baseName = "enabled")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.FIXES;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "folia.fix_piston_moving_issue";
+ }
+}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index c3a04ef842630b3df447dea48b84bccde0c89e83..9545f46c22cb7dcdf2412f9a741dc51be40faace 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -195,6 +195,7 @@ public class PistonMovingBlockEntity extends BlockEntity {
private static void moveEntityByPiston(Direction direction, Entity entity, double distance, Direction movementDirection) {
NOCLIP.set(direction);
+ if (me.earthme.luminol.config.modules.fixes.FoliaPistonIssueFixConfig.enabled) entity.setOldPosAndRot(); // Luminol- Try fixing folia issue #311
entity.move(
MoverType.PISTON,
new Vec3(

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sat, 11 Jan 2025 18:41:11 +0800
Subject: [PATCH] Merge Paper #11945 for temporary hooper behavior fix
A hopper optimization fix on Paper's pr : https://github.com/PaperMC/Paper/pull/11945
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 44aae845da6cd34fc00e0c71795d6f610679bd4b..df56451927d049c1baa5cd43ed0c25a3837474ec 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -764,8 +764,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
} else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
int j = Math.min(stack.getMaxStackSize(), to.getMaxStackSize()) - itemstack1.getCount(); // Paper - Make hoppers respect inventory max stack size
int k = Math.min(stack.getCount(), j);
-
- stack.shrink(k);
+ stack = stack.copy(true); // Paper - Perf: Optimize Hoppers
+ stack.shrink(k); // Paper - Perf: Optimize Hoppers
itemstack1.grow(k);
flag = k > 0;
}

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Kaiiju Vanilla end portal teleportation
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..bd3f0c807c36ecfb8a89a0ca68ffa0c3640b7423 100644
index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..64e081f993c2c844f83af227380b8a957eaabad4 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -114,6 +114,7 @@ import net.minecraft.world.level.block.Rotation;
@@ -33,7 +33,7 @@ index 4fdbdd1c5c937c20026afe555fa1c8371b4eaa16..bd3f0c807c36ecfb8a89a0ca68ffa0c3
portalInfoCompletable.complete(
new net.minecraft.world.level.portal.TeleportTransition(
- destination, Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, 90.0f, 0.0f,
+ destination, Vec3.atBottomCenterOf(targetPos.below()), this.getDeltaMovement(), 90.0f, 0.0f, // Kaiiju - Vanilla end teleportation
+ destination, finalPos, this.getDeltaMovement(), 90.0f, 0.0f, // Kaiiju - Vanilla end teleportation
TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET),
org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL
)

View File

@@ -83,7 +83,7 @@ index 5503d506c595296ecad09a3ce4497a365f216af5..98aef7a3cfc759e4415df3a56b5fe01e
if (!tickratemanager.isEntityFrozen(entity)) {
gameprofilerfiller.push("checkDespawn");
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index bd3f0c807c36ecfb8a89a0ca68ffa0c3640b7423..821fcf2bd1dacda191d7c8c17199069ebb9e73d3 100644
index 64e081f993c2c844f83af227380b8a957eaabad4..15cbbd8c660b8544bd39c8f4ebe8e44922fe81b1 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -390,6 +390,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -0,0 +1,249 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: adabugra <57899270+adabugra@users.noreply.github.com>
Date: Mon, 6 Jan 2025 19:24:05 +0300
Subject: [PATCH] Pufferfish: Sentry
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b830cb288ceba390ed39cd33fc1ee855357a97e
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java
@@ -0,0 +1,133 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import io.sentry.Breadcrumb;
+import io.sentry.Sentry;
+import io.sentry.SentryEvent;
+import io.sentry.SentryLevel;
+import io.sentry.protocol.Message;
+import io.sentry.protocol.User;
+
+import java.util.Map;
+
+import me.earthme.luminol.config.modules.misc.SentryConfig;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.filter.AbstractFilter;
+
+public class PufferfishSentryAppender extends AbstractAppender {
+
+ private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(PufferfishSentryAppender.class.getSimpleName());
+ private static final Gson GSON = new Gson();
+ private final Level logLevel;
+
+ public PufferfishSentryAppender(Level logLevel) {
+ super("PufferfishSentryAdapter", new SentryFilter(), null);
+ this.logLevel = logLevel;
+ }
+
+ @Override
+ public void append(LogEvent logEvent) {
+ if (logEvent.getLevel().isMoreSpecificThan(logLevel) && (logEvent.getThrown() != null || !SentryConfig.onlyLogThrown)) {
+ try {
+ logException(logEvent);
+ } catch (Exception e) {
+ logger.warn("Failed to log event with sentry", e);
+ }
+ } else {
+ try {
+ logBreadcrumb(logEvent);
+ } catch (Exception e) {
+ logger.warn("Failed to log event with sentry", e);
+ }
+ }
+ }
+
+ private void logException(LogEvent e) {
+ SentryEvent event = new SentryEvent(e.getThrown());
+
+ Message sentryMessage = new Message();
+ sentryMessage.setMessage(e.getMessage().getFormattedMessage());
+
+ event.setThrowable(e.getThrown());
+ event.setLevel(getLevel(e.getLevel()));
+ event.setLogger(e.getLoggerName());
+ event.setTransaction(e.getLoggerName());
+ event.setExtra("thread_name", e.getThreadName());
+
+ boolean hasContext = e.getContextData() != null;
+
+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_playerid")) {
+ User user = new User();
+ user.setId(e.getContextData().getValue("pufferfishsentry_playerid"));
+ user.setUsername(e.getContextData().getValue("pufferfishsentry_playername"));
+ event.setUser(user);
+ }
+
+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_pluginname")) {
+ event.setExtra("plugin.name", e.getContextData().getValue("pufferfishsentry_pluginname"));
+ event.setExtra("plugin.version", e.getContextData().getValue("pufferfishsentry_pluginversion"));
+ event.setTransaction(e.getContextData().getValue("pufferfishsentry_pluginname"));
+ }
+
+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_eventdata")) {
+ Map<String, String> eventFields = GSON.fromJson((String) e.getContextData().getValue("pufferfishsentry_eventdata"), new TypeToken<Map<String, String>>() {
+ }.getType());
+ if (eventFields != null) {
+ event.setExtra("event", eventFields);
+ }
+ }
+
+ Sentry.captureEvent(event);
+ }
+
+ private void logBreadcrumb(LogEvent e) {
+ Breadcrumb breadcrumb = new Breadcrumb();
+
+ breadcrumb.setLevel(getLevel(e.getLevel()));
+ breadcrumb.setCategory(e.getLoggerName());
+ breadcrumb.setType(e.getLoggerName());
+ breadcrumb.setMessage(e.getMessage().getFormattedMessage());
+
+ Sentry.addBreadcrumb(breadcrumb);
+ }
+
+ private SentryLevel getLevel(Level level) {
+ return switch (level.getStandardLevel()) {
+ case TRACE, DEBUG -> SentryLevel.DEBUG;
+ case WARN -> SentryLevel.WARNING;
+ case ERROR -> SentryLevel.ERROR;
+ case FATAL -> SentryLevel.FATAL;
+ default -> SentryLevel.INFO;
+ };
+ }
+
+ private static class SentryFilter extends AbstractFilter {
+
+ @Override
+ public Result filter(Logger logger, Level level, Marker marker, String msg,
+ Object... params) {
+ return this.filter(logger.getName());
+ }
+
+ @Override
+ public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
+ return this.filter(logger.getName());
+ }
+
+ @Override
+ public Result filter(LogEvent event) {
+ return this.filter(event == null ? null : event.getLoggerName());
+ }
+
+ private Result filter(String loggerName) {
+ return loggerName != null && loggerName.startsWith("gg.castaway.pufferfish.sentry") ? Result.DENY
+ : Result.NEUTRAL;
+ }
+ }
+}
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c01e5b5de685eca7edbe8a87732efd45d4dd2557
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java
@@ -0,0 +1,44 @@
+package gg.pufferfish.pufferfish.sentry;
+
+import io.sentry.Sentry;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class SentryManager {
+
+ private static final Logger logger = LogManager.getLogger(SentryManager.class);
+
+ private SentryManager() {
+
+ }
+
+ private static boolean initialized = false;
+
+ public static synchronized void init(Level logLevel) {
+ if (initialized) {
+ return;
+ }
+ if (logLevel == null) {
+ logger.error("Invalid log level, defaulting to WARN.");
+ logLevel = Level.WARN;
+ }
+ try {
+ initialized = true;
+
+ Sentry.init(options -> {
+ options.setDsn(me.earthme.luminol.config.modules.misc.SentryConfig.sentryDsn);
+ options.setMaxBreadcrumbs(100);
+ });
+
+ PufferfishSentryAppender appender = new PufferfishSentryAppender(logLevel);
+ appender.start();
+ ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).addAppender(appender);
+ logger.info("Sentry logging started!");
+ } catch (Exception e) {
+ logger.warn("Failed to initialize sentry!", e);
+ initialized = false;
+ }
+ }
+
+}
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..55d6bb635b182d15471bfcd481a2b7c6ce26c00b
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/SentryConfig.java
@@ -0,0 +1,47 @@
+package me.earthme.luminol.config.modules.misc;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import org.apache.logging.log4j.Level;
+
+public class SentryConfig implements IConfigModule {
+
+ @ConfigInfo(baseName = "dsn", comments =
+ " Sentry DSN for improved error logging, leave blank to disable,\n" +
+ " Obtain from https://sentry.io/")
+ public static String sentryDsn = "";
+
+ @ConfigInfo(baseName = "log_level", comments = " Logs with a level higher than or equal to this level will be recorded.")
+ public static String logLevel = "WARN";
+
+ @ConfigInfo(baseName = "only_log_thrown", comments = " Only log with a Throwable will be recorded after enabling this.")
+ public static boolean onlyLogThrown = true;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "sentry";
+ }
+
+ @Override
+ public void onLoaded(CommentedFileConfig configInstance) {
+ String sentryEnvironment = System.getenv("SENTRY_DSN");
+
+ sentryDsn = sentryEnvironment != null && !sentryEnvironment.isBlank()
+ ? sentryEnvironment
+ : configInstance.getOrElse("sentry.dsn", sentryDsn);
+
+ logLevel = configInstance.getOrElse("sentry.log-level", logLevel);
+ onlyLogThrown = configInstance.getOrElse("sentry.only-log-thrown", onlyLogThrown);
+
+ if (sentryDsn != null && !sentryDsn.isBlank()) {
+ gg.pufferfish.pufferfish.sentry.SentryManager.init(Level.getLevel(logLevel));
+ }
+ }
+}
\ No newline at end of file

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Gale Optimize sun burn tick
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 821fcf2bd1dacda191d7c8c17199069ebb9e73d3..9c29f99c9426db12231d7423ca24ca6fecf9c868 100644
index 15cbbd8c660b8544bd39c8f4ebe8e44922fe81b1..ae3af52c8b6368e40e39bcd9ecd8e2cdcb0b9c5b 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -274,7 +274,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Gale Skip entity move if movement is zero
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 9c29f99c9426db12231d7423ca24ca6fecf9c868..3b2bce1b5261a0efbbfcd7d38bf7f093d97df3a6 100644
index ae3af52c8b6368e40e39bcd9ecd8e2cdcb0b9c5b..b6aaa238626bc747379f991c17c279de52907083 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -283,6 +283,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -179,10 +179,10 @@ index de2f03d6e771c09e8da2da454b7ec4a16c0a17ab..0b7347e8fdf995900221ee4aa4e97a4d
if (mspt == -1){
return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3));
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index c7390e0341cd19fa5e0b21882f27943174f718d0..19e1dfbcd69e3f960d148b014e9e9248072918a2 100644
index 55bac6e6cccce6e0282936ac78bbe82628daa655..2cff9edf247587dffaac5405127de0afc17dc7c0 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1802,6 +1802,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1801,6 +1801,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_SCHEDULER_TICK); } // Folia - profiler
}
// Folia end - region threading
@@ -212,7 +212,7 @@ index c7390e0341cd19fa5e0b21882f27943174f718d0..19e1dfbcd69e3f960d148b014e9e9248
if (region == null) this.tickRateManager.tick(); // Folia - region threading
this.tickChildren(shouldKeepTicking, region); // Folia - region threading
if (region == null && i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading
@@ -1810,6 +1833,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1809,6 +1832,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Folia - region threading
@@ -332,7 +332,7 @@ index 921527acc8624536f4a48e9fdf7fce370bc52c77..497de02dce0f397ce261b4d62777e11f
+ // KioCG end
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 3b2bce1b5261a0efbbfcd7d38bf7f093d97df3a6..2d9f75526240689facba1a4fbef7d40ef8299a1d 100644
index b6aaa238626bc747379f991c17c279de52907083..3700f7c1893e9ccdcef04ae1fab5d7c97c5a91d7 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -6236,4 +6236,6 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -0,0 +1,887 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: adabugra <57899270+adabugra@users.noreply.github.com>
Date: Sun, 5 Jan 2025 12:32:26 +0300
Subject: [PATCH] Leaf Secure Seed with SecureSeed command
diff --git a/build.gradle.kts b/build.gradle.kts
index fbf51f738e98ac6e8358a7fa81b7fc545469a5a6..6e1a9ee0ebea5c313d568ac276db1f38476681e2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -33,7 +33,7 @@ dependencies {
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
implementation("net.minecrell:terminalconsoleappender:1.3.0")
- implementation("net.kyori:adventure-text-serializer-ansi:4.17.0") // Keep in sync with adventureVersion from Paper-API build file
+ implementation("net.kyori:adventure-text-serializer-ansi:4.18.0") // Keep in sync with adventureVersion from Paper-API build file // Leaves - Fix color in console
/*
Required to add the missing Log4j2Plugins.dat file from log4j-core
which has been removed by Mojang. Without it, log4j has to classload
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae3014ddee1994c551e206ac9a94b414cf6bc94b
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/SecureSeedConfig.java
@@ -0,0 +1,25 @@
+package me.earthme.luminol.config.modules.misc;
+
+import me.earthme.luminol.config.ConfigInfo;
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.HotReloadUnsupported;
+import me.earthme.luminol.config.IConfigModule;
+
+public class SecureSeedConfig implements IConfigModule {
+
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "enabled", comments =
+ "Once you enable secure seed, all ores and structures are generated with 1024-bit seed\n" +
+ " instead of using 64-bit seed in vanilla, made seed cracker become impossible.")
+ public static boolean enabled = false;
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "secure_seed";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/commands/SeedCommand.java b/src/main/java/net/minecraft/server/commands/SeedCommand.java
index 0b500b19a99fa6c2740c0db350a166462668df9c..1b82a5cc73cf7916146d6687a225256615551507 100644
--- a/src/main/java/net/minecraft/server/commands/SeedCommand.java
+++ b/src/main/java/net/minecraft/server/commands/SeedCommand.java
@@ -12,6 +12,17 @@ public class SeedCommand {
long l = context.getSource().getLevel().getSeed();
Component component = ComponentUtils.copyOnClickText(String.valueOf(l));
context.getSource().sendSuccess(() -> Component.translatable("commands.seed.success", component), false);
+
+ // Leaf start - Matter - SecureSeed Command
+ if (me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
+ su.plo.matter.Globals.setupGlobals(context.getSource().getLevel());
+ String seedStr = su.plo.matter.Globals.seedToString(su.plo.matter.Globals.worldSeed);
+ Component featureSeedComponent = ComponentUtils.copyOnClickText(seedStr);
+
+ context.getSource().sendSuccess(() -> Component.translatable(("Feature seed: %s"), featureSeedComponent), false);
+ }
+ // Leaf end - Matter - SecureSeed Command
+
return (int)l;
}));
}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
index c3ec370b83b895be0f03662e3884fa4a2442a2a6..d53679891422a4a9cd13382869469c4848db8ede 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
@@ -166,7 +166,17 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
boolean flag = this.get("generate-structures", true);
long i = WorldOptions.parseSeed(s).orElse(WorldOptions.randomSeed());
- this.worldOptions = new WorldOptions(i, flag, false);
+ // Leaf start - Matter - Feature Secure Seed
+ if (me.earthme.luminol.config.modules.misc.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(i, featureSeed, flag, false);
+ } else {
+ this.worldOptions = new WorldOptions(i, flag, false);
+ }
+ // Leaf end - Matter - Feature Secure Seed
this.worldDimensionData = new DedicatedServerProperties.WorldDimensionData((JsonObject) this.get("generator-settings", (s1) -> {
return GsonHelper.parse(!s1.isEmpty() ? s1 : "{}");
}, new JsonObject()), (String) this.get("level-type", (s1) -> {
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index ca47a512452ae425160e30dc7c4a79f40aa97a26..0701c559bc81f265e8f07885af8b08ebf7025ccd 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -675,6 +675,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
}
public ChunkGenerator getGenerator() {
+ su.plo.matter.Globals.setupGlobals(level); // Leaf - Matter - Feature Secure Seed
return this.chunkMap.generator();
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index f8dfaa6170962f5b06a0a8ccbf3d8677381babcf..c910b06fdf90434502185d7784b02b1adeab4c8a 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -630,6 +630,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen);
}
// CraftBukkit end
+ su.plo.matter.Globals.setupGlobals(this); // Leaf - Matter - Feature Secure Seed
boolean flag2 = minecraftserver.forceSynchronousWrites();
DataFixer datafixer = minecraftserver.getFixerUpper();
EntityPersistentStorage<Entity> entitypersistentstorage = new EntityStorage(new SimpleRegionStorage(new RegionStorageInfo(convertable_conversionsession.getLevelId(), resourcekey, "entities"), convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, DataFixTypes.ENTITY_CHUNK), this, minecraftserver);
diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java
index 72346a7e5269c91e3143933ac37e65ad9639b791..2103769c0a3171e594181308510aedf7a1a3c768 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
@@ -353,7 +353,12 @@ public class Slime extends Mob implements Enemy {
}
ChunkPos chunkcoordintpair = new ChunkPos(pos);
- boolean flag = world.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
+ // Leaf start - Matter - Feature Secure Seed
+ boolean isSlimeChunk = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? world.getChunk(chunkcoordintpair.x, chunkcoordintpair.z).isSlimeChunk()
+ : WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
+ boolean flag = world.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
+ // Leaf end - Matter - Feature Secure Seed
// Paper start - Replace rules for Height in Slime Chunks
final double maxHeightSlimeChunk = world.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index f87abb22dd161b2b74401086de80dc95c9ac2dbb..84e92f9f51d82c77f101484b51fd119386756da7 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -85,6 +85,11 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
protected final LevelHeightAccessor levelHeightAccessor;
protected final LevelChunkSection[] sections;
+ // Leaf start - Matter - Feature Secure Seed
+ private boolean slimeChunk;
+ private boolean hasComputedSlimeChunk;
+ // Leaf end - Matter - Feature Secure Seed
+
// CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading.
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);
@@ -189,6 +194,17 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
return GameEventListenerRegistry.NOOP;
}
+ // Leaf start - Matter - Feature 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 - Feature Secure Seed
+
public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
@Nullable
public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean moved);
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
index 7f6dd454e0794739dc1861f768aaed86c484afe7..bf5dce738e84e6b19743bf46b35e6116024d9f0e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -345,7 +345,11 @@ public abstract class ChunkGenerator {
return structure.step().ordinal();
}));
List<FeatureSorter.StepFeatureData> list = (List) this.featuresPerStep.get();
- WorldgenRandom seededrandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom seededrandom = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new su.plo.matter.WorldgenCryptoRandom(blockposition.getX(), blockposition.getZ(), su.plo.matter.Globals.Salt.UNDEFINED, 0)
+ : new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
+ // Leaf end - Matter - Feature Secure Seed
long i = seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), blockposition.getX(), blockposition.getZ());
Set<Holder<Biome>> set = new ObjectArraySet();
@@ -584,9 +588,18 @@ public abstract class ChunkGenerator {
ArrayList<StructureSet.StructureSelectionEntry> arraylist = new ArrayList(list.size());
arraylist.addAll(list);
- WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(0L));
-
- seededrandom.setLargeFeatureSeed(placementCalculator.getLevelSeed(), chunkcoordintpair.x, chunkcoordintpair.z);
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom seededrandom;
+ if (me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
+ seededrandom = new su.plo.matter.WorldgenCryptoRandom(
+ chunkcoordintpair.x, chunkcoordintpair.z, su.plo.matter.Globals.Salt.GENERATE_FEATURE, 0
+ );
+ } else {
+ seededrandom = new WorldgenRandom(new LegacyRandomSource(0L));
+
+ seededrandom.setLargeFeatureSeed(placementCalculator.getLevelSeed(), chunkcoordintpair.x, chunkcoordintpair.z);
+ }
+ // Leaf end - Matter - Feature Secure Seed
int i = 0;
StructureSet.StructureSelectionEntry structureset_a1;
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
index a20520a6bd28bae1cee82258ac49d9753faba2bd..2dba92926251c0c123d4dc9beb473a7078cc40cb 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
@@ -224,8 +224,12 @@ public class ChunkGeneratorStructureState {
List<CompletableFuture<ChunkPos>> list = new ArrayList(j);
int k = placement.spread();
HolderSet<Biome> holderset = placement.preferredBiomes();
- RandomSource randomsource = RandomSource.create();
+ // Leaf start - Matter - Feature Secure Seed
+ RandomSource randomsource = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.STRONGHOLDS, 0)
+ : RandomSource.create();
+ if (!me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
// Paper start - Add missing structure set seed configs
if (this.conf.strongholdSeed != null && structureSetEntry.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
randomsource.setSeed(this.conf.strongholdSeed);
@@ -233,6 +237,7 @@ public class ChunkGeneratorStructureState {
// Paper end - Add missing structure set seed configs
randomsource.setSeed(this.concentricRingsSeed);
} // Paper - Add missing structure set seed configs
+ }// Leaf end - Matter - Feature Secure Seed
double d0 = randomsource.nextDouble() * Math.PI * 2.0D;
int l = 0;
int i1 = 0;
diff --git a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStep.java b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStep.java
index f9aad1b8c02b70e620efdc2a58cadf4fff0f3ed5..78d6553fc4cbe18bb94f477f890f02d8970af35d 100644
--- a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStep.java
+++ b/src/main/java/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(WorldGenContext context, StaticCache2D<GenerationChunkHolder> staticCache2D, ChunkAccess chunk) {
+ su.plo.matter.Globals.setupGlobals(context.level()); // Leaf - Matter - Feature 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, staticCache2D, chunk).thenApply(generated -> this.completeChunkGeneration(generated, profiledDuration));
diff --git a/src/main/java/net/minecraft/world/level/levelgen/WorldOptions.java b/src/main/java/net/minecraft/world/level/levelgen/WorldOptions.java
index 41c19e4e7bde4632879da564f52f3d373de27ec4..fd3ebfff98ab67082a4cfe482dc5ef66a95206c0 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/WorldOptions.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/WorldOptions.java
@@ -9,17 +9,35 @@ import net.minecraft.util.RandomSource;
import org.apache.commons.lang3.StringUtils;
public class WorldOptions {
+ // Leaf start - Matter - Feature 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.misc.SecureSeedConfig.enabled;
public static final MapCodec<WorldOptions> CODEC = RecordCodecBuilder.mapCodec(
- instance -> instance.group(
- Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
- 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(generatorOptions -> generatorOptions.legacyCustomOptions)
- )
- .apply(instance, instance.stable(WorldOptions::new))
+ instance -> isSecureSeedEnabled
+ ? instance.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(generatorOptions -> generatorOptions.legacyCustomOptions)
+ )
+ .apply(instance, instance.stable(WorldOptions::new))
+ : instance.group(
+ Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
+ 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(generatorOptions -> generatorOptions.legacyCustomOptions)
+ )
+ .apply(instance, instance.stable(WorldOptions::new))
);
- public static final WorldOptions DEMO_OPTIONS = new WorldOptions((long)"North Carolina".hashCode(), true, true);
+ // Leaf end - Matter - Feature Secure Seed
+ // Leaf start - Matter - Feature 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 - Feature Secure Seed
private final long seed;
+ private long[] featureSeed = su.plo.matter.Globals.createRandomWorldSeed(); // Leaf - Matter - Feature Secure Seed
private final boolean generateStructures;
private final boolean generateBonusChest;
private final Optional<String> legacyCustomOptions;
@@ -28,14 +46,35 @@ public class WorldOptions {
this(seed, generateStructures, bonusChest, Optional.empty());
}
+ // Leaf start - Matter - Feature 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 - Feature Secure Seed
+
public static WorldOptions defaultWithRandomSeed() {
- return new WorldOptions(randomSeed(), true, false);
+ // Leaf start - Matter - Feature Secure Seed
+ return isSecureSeedEnabled
+ ? new WorldOptions(randomSeed(), su.plo.matter.Globals.createRandomWorldSeed(), true, false)
+ : new WorldOptions(randomSeed(), true, false);
+ // Leaf end - Matter - Feature Secure Seed
}
public static WorldOptions testWorldWithRandomSeed() {
return new WorldOptions(randomSeed(), false, false);
}
+ // Leaf start - Matter - Feature 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 - Feature Secure Seed
+
private WorldOptions(long seed, boolean generateStructures, boolean bonusChest, Optional<String> legacyCustomOptions) {
this.seed = seed;
this.generateStructures = generateStructures;
@@ -47,6 +86,16 @@ public class WorldOptions {
return this.seed;
}
+ // Leaf start - Matter - Feature Secure Seed
+ public long[] featureSeed() {
+ return this.featureSeed;
+ }
+
+ public String featureSeedSerialize() {
+ return gson.toJson(this.featureSeed);
+ }
+ // Leaf end - Matter - Feature Secure Seed
+
public boolean generateStructures() {
return this.generateStructures;
}
@@ -59,17 +108,25 @@ public class WorldOptions {
return this.legacyCustomOptions.isPresent();
}
+ // Leaf start - Matter - Feature Secure Seed
public WorldOptions withBonusChest(boolean bonusChest) {
- return new WorldOptions(this.seed, this.generateStructures, bonusChest, this.legacyCustomOptions);
+ return isSecureSeedEnabled
+ ? new WorldOptions(this.seed, this.featureSeed, this.generateStructures, bonusChest, this.legacyCustomOptions)
+ : new WorldOptions(this.seed, this.generateStructures, bonusChest, this.legacyCustomOptions);
}
public WorldOptions withStructures(boolean structures) {
- return new WorldOptions(this.seed, structures, this.generateBonusChest, this.legacyCustomOptions);
+ return isSecureSeedEnabled
+ ? new WorldOptions(this.seed, this.featureSeed, structures, this.generateBonusChest, this.legacyCustomOptions)
+ : new WorldOptions(this.seed, structures, this.generateBonusChest, this.legacyCustomOptions);
}
public WorldOptions withSeed(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 - Feature Secure Seed
public static OptionalLong parseSeed(String seed) {
seed = seed.trim();
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/GeodeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
index 270db8b29cdf65e9bb932637425214eefeca86b7..c699b671449434355fc23b4c703099ac192064f8 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
@@ -41,7 +41,11 @@ public class GeodeFeature extends Feature<GeodeConfiguration> {
int j = geodeConfiguration.maxGenOffset;
List<Pair<BlockPos, Integer>> list = Lists.newLinkedList();
int k = geodeConfiguration.distributionPoints.sample(randomSource);
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(worldGenLevel.getSeed()));
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom worldgenRandom = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.GEODE_FEATURE, 0)
+ : new WorldgenRandom(new LegacyRandomSource(worldGenLevel.getSeed()));
+ // Leaf end - Matter - Feature Secure Seed
NormalNoise normalNoise = NormalNoise.create(worldgenRandom, -4, 1.0);
List<BlockPos> list2 = Lists.newLinkedList();
double d = (double)k / (double)geodeConfiguration.outerWallDistance.getMaxValue();
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
index 13f7fce1959c0f44e047616674198176e667067f..11ad7f9e8a050f69b6936d0a31136ece7450b49e 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/Structure.java
@@ -248,6 +248,13 @@ public abstract class Structure {
}
private static WorldgenRandom makeRandom(long seed, ChunkPos chunkPos) {
+ // Leaf start - Matter - Feature Secure Seed
+ if (me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
+ return new su.plo.matter.WorldgenCryptoRandom(
+ chunkPos.x, chunkPos.z, su.plo.matter.Globals.Salt.GENERATE_FEATURE, seed
+ );
+ }
+ // Leaf end - Matter - Feature Secure Seed
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
worldgenRandom.setLargeFeatureSeed(seed, chunkPos.x, chunkPos.z);
return worldgenRandom;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
index f873a0a0734b4fe74ba5b5f8ae0cc3c78fa76b9f..a9724579c41a591462c2b85659433cd41fff217e 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
@@ -71,8 +71,17 @@ public class RandomSpreadStructurePlacement extends StructurePlacement {
public ChunkPos getPotentialStructureChunk(long seed, int chunkX, int chunkZ) {
int i = Math.floorDiv(chunkX, this.spacing);
int j = Math.floorDiv(chunkZ, this.spacing);
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
- worldgenRandom.setLargeFeatureWithSalt(seed, i, j, this.salt());
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom worldgenRandom;
+ if (me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
+ worldgenRandom = new su.plo.matter.WorldgenCryptoRandom(
+ i, j, su.plo.matter.Globals.Salt.POTENTIONAL_FEATURE, this.salt
+ );
+ } else {
+ worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
+ worldgenRandom.setLargeFeatureWithSalt(seed, i, j, this.salt());
+ }
+ // Leaf end - Matter - Feature Secure Seed
int k = this.spacing - this.separation;
int l = this.spreadType.evaluate(worldgenRandom, k);
int m = this.spreadType.evaluate(worldgenRandom, k);
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
index cbf13e4f2da6a27619e9bc9a7cd73bb6e69cad2a..47171ec6f2c00c79e66af974ec32bbf1f88c1ebb 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
@@ -118,8 +118,17 @@ public abstract class StructurePlacement {
public abstract StructurePlacementType<?> type();
private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
- worldgenRandom.setLargeFeatureWithSalt(seed, salt, chunkX, chunkZ);
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom worldgenRandom;
+ if (me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) {
+ worldgenRandom = new su.plo.matter.WorldgenCryptoRandom(
+ chunkX, chunkZ, su.plo.matter.Globals.Salt.UNDEFINED, salt
+ );
+ } else {
+ worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
+ worldgenRandom.setLargeFeatureWithSalt(seed, salt, chunkX, chunkZ);
+ }
+ // Leaf end - Matter - Feature Secure Seed
return worldgenRandom.nextFloat() < frequency;
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
index 65a0d9e7dd742732974774daabce02e9e52039ac..e4aa8f17f3a1fc0bdea43386f2dfdb7464a9b288 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
+++ b/src/main/java/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 levelHeightAccessor = context.heightAccessor();
- WorldgenRandom worldgenRandom = context.random();
+ // Leaf start - Matter - Feature Secure Seed
+ WorldgenRandom worldgenRandom = me.earthme.luminol.config.modules.misc.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 - Feature Secure Seed
Registry<StructureTemplatePool> registry = registryAccess.lookupOrThrow(Registries.TEMPLATE_POOL);
Rotation rotation = Rotation.getRandom(worldgenRandom);
StructureTemplatePool structureTemplatePool = structurePool.unwrapKey()
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/structures/EndCityStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/structures/EndCityStructure.java
index 712c6431d63e0b1a1edd9d7de9b13c46a1acb469..35dc49d90aa6d660a60fb76efddb530f9ec59666 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/structures/EndCityStructure.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/structures/EndCityStructure.java
@@ -10,6 +10,7 @@ import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.StructureType;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder;
+//import su.plo.matter.WorldgenCryptoRandom; // Leaf - Matter - Feature Secure Seed
public class EndCityStructure extends Structure {
public static final MapCodec<EndCityStructure> CODEC = simpleCodec(EndCityStructure::new);
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/structures/MineshaftStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/structures/MineshaftStructure.java
index 7f4c5e9355a6f562f668e9b8134bfe65dde35f90..7a1c21696f6531c7dded774f45073df16732f252 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/structures/MineshaftStructure.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/structures/MineshaftStructure.java
@@ -20,6 +20,7 @@ import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructureType;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePiecesBuilder;
+//import su.plo.matter.WorldgenCryptoRandom; // Leaf - Matter - Feature Secure Seed
public class MineshaftStructure extends Structure {
public static final MapCodec<MineshaftStructure> CODEC = RecordCodecBuilder.mapCodec(
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index 4791e013e8257f57b5db6f974dc05829b911cfa0..f9eb72f761d50c585145c3a43e2c88ae058cc265 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -206,7 +206,12 @@ public class CraftChunk implements Chunk {
@Override
public boolean isSlimeChunk() {
// 987234911L is deterimined in EntitySlime when seeing if a slime can spawn in a chunk
- return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ // Leaf start - Matter - Feature Secure Seed
+ boolean isSlimeChunk = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? worldServer.getChunk(this.getX(), this.getZ()).isSlimeChunk()
+ : WorldgenRandom.seedSlimeChunk(this.getX(), this.getZ(), this.getWorld().getSeed(), worldServer.spigotConfig.slimeSeed).nextInt(10) == 0; // Paper
+ return this.worldServer.paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
+ // Leaf end - Matter - Feature Secure Seed
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 20cf4ce4f73f681bdbe092d4693812800c953be9..aecd4c5767a5c91ca60db395b6f412950aa77b26 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1426,7 +1426,11 @@ public final class CraftServer implements Server {
iregistrycustom_dimension = leveldataanddimensions.dimensions().dimensionsRegistryAccess();
} else {
LevelSettings worldsettings;
- WorldOptions worldoptions = new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf start - Matter - Feature Secure Seed
+ WorldOptions worldoptions = me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled
+ ? new WorldOptions(creator.seed(), su.plo.matter.Globals.createRandomWorldSeed(), creator.generateStructures(), false)
+ : new WorldOptions(creator.seed(), creator.generateStructures(), false);
+ // Leaf end - Matter - Feature Secure Seed
WorldDimensions worlddimensions;
DedicatedServerProperties.WorldDimensionData properties = new DedicatedServerProperties.WorldDimensionData(GsonHelper.parse((creator.generatorSettings().isEmpty()) ? "{}" : creator.generatorSettings()), creator.type().name().toLowerCase(Locale.ROOT));
diff --git a/src/main/java/su/plo/matter/Globals.java b/src/main/java/su/plo/matter/Globals.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1db02231b6c10c2da98e24147b5377fb0b8179c
--- /dev/null
+++ b/src/main/java/su/plo/matter/Globals.java
@@ -0,0 +1,94 @@
+package su.plo.matter;
+
+import com.google.common.collect.Iterables;
+import net.minecraft.server.level.ServerLevel;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Optional;
+
+public class Globals {
+ public static final int WORLD_SEED_LONGS = 16;
+ public static final int WORLD_SEED_BITS = WORLD_SEED_LONGS * 64;
+
+ public static final long[] worldSeed = new long[WORLD_SEED_LONGS];
+ public static final ThreadLocal<Integer> dimension = ThreadLocal.withInitial(() -> 0);
+
+ public static void setupGlobals(ServerLevel world) {
+ if (!me.earthme.luminol.config.modules.misc.SecureSeedConfig.enabled) return;
+
+ long[] seed = world.getServer().getWorldData().worldGenOptions().featureSeed();
+ System.arraycopy(seed, 0, worldSeed, 0, WORLD_SEED_LONGS);
+ int worldIndex = Iterables.indexOf(world.getServer().levelKeys(), it -> it == world.dimension());
+ if (worldIndex == -1)
+ worldIndex = world.getServer().levelKeys().size(); // if we are in world construction it may not have been added to the map yet
+ dimension.set(worldIndex);
+ }
+
+ public static long[] createRandomWorldSeed() {
+ long[] seed = new long[WORLD_SEED_LONGS];
+ SecureRandom rand = new SecureRandom();
+ for (int i = 0; i < WORLD_SEED_LONGS; i++) {
+ seed[i] = rand.nextLong();
+ }
+ return seed;
+ }
+
+ // 1024-bit string -> 16 * 64 long[]
+ public static Optional<long[]> parseSeed(String seedStr) {
+ if (seedStr.isEmpty()) return Optional.empty();
+
+ if (seedStr.length() != WORLD_SEED_BITS) {
+ throw new IllegalArgumentException("Secure seed length must be " + WORLD_SEED_BITS + "-bit but found " + seedStr.length() + "-bit.");
+ }
+
+ long[] seed = new long[WORLD_SEED_LONGS];
+
+ for (int i = 0; i < WORLD_SEED_LONGS; i++) {
+ int start = i * 64;
+ int end = start + 64;
+ String seedSection = seedStr.substring(start, end);
+
+ BigInteger seedInDecimal = new BigInteger(seedSection, 2);
+ seed[i] = seedInDecimal.longValue();
+ }
+
+ return Optional.of(seed);
+ }
+
+ // 16 * 64 long[] -> 1024-bit string
+ public static String seedToString(long[] seed) {
+ StringBuilder sb = new StringBuilder();
+
+ for (long longV : seed) {
+ // Convert to 64-bit binary string per long
+ // Use format to keep 64-bit length, and use 0 to complete space
+ String binaryStr = String.format("%64s", Long.toBinaryString(longV)).replace(' ', '0');
+
+ sb.append(binaryStr);
+ }
+
+ return sb.toString();
+ }
+
+ public enum Salt {
+ UNDEFINED,
+ BASTION_FEATURE,
+ WOODLAND_MANSION_FEATURE,
+ MINESHAFT_FEATURE,
+ BURIED_TREASURE_FEATURE,
+ NETHER_FORTRESS_FEATURE,
+ PILLAGER_OUTPOST_FEATURE,
+ GEODE_FEATURE,
+ NETHER_FOSSIL_FEATURE,
+ OCEAN_MONUMENT_FEATURE,
+ RUINED_PORTAL_FEATURE,
+ POTENTIONAL_FEATURE,
+ GENERATE_FEATURE,
+ JIGSAW_PLACEMENT,
+ STRONGHOLDS,
+ POPULATION,
+ DECORATION,
+ SLIME_CHUNK
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/plo/matter/Hashing.java b/src/main/java/su/plo/matter/Hashing.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f0fca108ac61566bda3c1ac16911ced86af47a1
--- /dev/null
+++ b/src/main/java/su/plo/matter/Hashing.java
@@ -0,0 +1,73 @@
+package su.plo.matter;
+
+public class Hashing {
+ // https://en.wikipedia.org/wiki/BLAKE_(hash_function)
+ // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/digests/Blake2bDigest.java
+
+ private final static long[] blake2b_IV = {
+ 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL,
+ 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL,
+ 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L
+ };
+
+ private final static byte[][] blake2b_sigma = {
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+ {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
+ {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
+ {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
+ {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
+ {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
+ {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
+ {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
+ {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}
+ };
+
+ public static long[] hashWorldSeed(long[] worldSeed) {
+ long[] result = blake2b_IV.clone();
+ result[0] ^= 0x01010040;
+ hash(worldSeed, result, new long[16], 0, false);
+ return result;
+ }
+
+ public static void hash(long[] message, long[] chainValue, long[] internalState, long messageOffset, boolean isFinal) {
+ assert message.length == 16;
+ assert chainValue.length == 8;
+ assert internalState.length == 16;
+
+ System.arraycopy(chainValue, 0, internalState, 0, chainValue.length);
+ System.arraycopy(blake2b_IV, 0, internalState, chainValue.length, 4);
+ internalState[12] = messageOffset ^ blake2b_IV[4];
+ internalState[13] = blake2b_IV[5];
+ if (isFinal) internalState[14] = ~blake2b_IV[6];
+ internalState[15] = blake2b_IV[7];
+
+ for (int round = 0; round < 12; round++) {
+ G(message[blake2b_sigma[round][0]], message[blake2b_sigma[round][1]], 0, 4, 8, 12, internalState);
+ G(message[blake2b_sigma[round][2]], message[blake2b_sigma[round][3]], 1, 5, 9, 13, internalState);
+ G(message[blake2b_sigma[round][4]], message[blake2b_sigma[round][5]], 2, 6, 10, 14, internalState);
+ G(message[blake2b_sigma[round][6]], message[blake2b_sigma[round][7]], 3, 7, 11, 15, internalState);
+ G(message[blake2b_sigma[round][8]], message[blake2b_sigma[round][9]], 0, 5, 10, 15, internalState);
+ G(message[blake2b_sigma[round][10]], message[blake2b_sigma[round][11]], 1, 6, 11, 12, internalState);
+ G(message[blake2b_sigma[round][12]], message[blake2b_sigma[round][13]], 2, 7, 8, 13, internalState);
+ G(message[blake2b_sigma[round][14]], message[blake2b_sigma[round][15]], 3, 4, 9, 14, internalState);
+ }
+
+ for (int i = 0; i < 8; i++) {
+ chainValue[i] ^= internalState[i] ^ internalState[i + 8];
+ }
+ }
+
+ private static void G(long m1, long m2, int posA, int posB, int posC, int posD, long[] internalState) {
+ internalState[posA] = internalState[posA] + internalState[posB] + m1;
+ internalState[posD] = Long.rotateRight(internalState[posD] ^ internalState[posA], 32);
+ internalState[posC] = internalState[posC] + internalState[posD];
+ internalState[posB] = Long.rotateRight(internalState[posB] ^ internalState[posC], 24); // replaces 25 of BLAKE
+ internalState[posA] = internalState[posA] + internalState[posB] + m2;
+ internalState[posD] = Long.rotateRight(internalState[posD] ^ internalState[posA], 16);
+ internalState[posC] = internalState[posC] + internalState[posD];
+ internalState[posB] = Long.rotateRight(internalState[posB] ^ internalState[posC], 63); // replaces 11 of BLAKE
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/su/plo/matter/WorldgenCryptoRandom.java b/src/main/java/su/plo/matter/WorldgenCryptoRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa19e4bac4f4f128330faccbe5389b02afdf4887
--- /dev/null
+++ b/src/main/java/su/plo/matter/WorldgenCryptoRandom.java
@@ -0,0 +1,160 @@
+package su.plo.matter;
+
+import net.minecraft.util.Mth;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.levelgen.LegacyRandomSource;
+import net.minecraft.world.level.levelgen.WorldgenRandom;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+
+public class WorldgenCryptoRandom extends WorldgenRandom {
+ // hash the world seed to guard against badly chosen world seeds
+ private static final long[] HASHED_ZERO_SEED = Hashing.hashWorldSeed(new long[Globals.WORLD_SEED_LONGS]);
+ private static final ThreadLocal<long[]> LAST_SEEN_WORLD_SEED = ThreadLocal.withInitial(() -> new long[Globals.WORLD_SEED_LONGS]);
+ private static final ThreadLocal<long[]> HASHED_WORLD_SEED = ThreadLocal.withInitial(() -> HASHED_ZERO_SEED);
+
+ private static final int MAX_RANDOM_BIT_INDEX = 64 * 8;
+ private static final int LOG2_MAX_RANDOM_BIT_INDEX = 9;
+ private final long[] worldSeed = new long[Globals.WORLD_SEED_LONGS];
+ private final long[] randomBits = new long[8];
+ private final long[] message = new long[16];
+ private final long[] cachedInternalState = new long[16];
+ private int randomBitIndex;
+ private long counter;
+
+ public WorldgenCryptoRandom(int x, int z, Globals.Salt typeSalt, long salt) {
+ super(new LegacyRandomSource(0L));
+ if (typeSalt != null) {
+ this.setSecureSeed(x, z, typeSalt, salt);
+ }
+ }
+
+ public static RandomSource seedSlimeChunk(int chunkX, int chunkZ) {
+ return new WorldgenCryptoRandom(chunkX, chunkZ, Globals.Salt.SLIME_CHUNK, 0);
+ }
+
+ public void setSecureSeed(int x, int z, Globals.Salt typeSalt, long salt) {
+ System.arraycopy(Globals.worldSeed, 0, this.worldSeed, 0, Globals.WORLD_SEED_LONGS);
+ message[0] = ((long) x << 32) | ((long) z & 0xffffffffL);
+ message[1] = ((long) Globals.dimension.get() << 32) | ((long) salt & 0xffffffffL);
+ message[2] = typeSalt.ordinal();
+ message[3] = counter = 0;
+ randomBitIndex = MAX_RANDOM_BIT_INDEX;
+ }
+
+ private long[] getHashedWorldSeed() {
+ if (!Arrays.equals(worldSeed, LAST_SEEN_WORLD_SEED.get())) {
+ HASHED_WORLD_SEED.set(Hashing.hashWorldSeed(worldSeed));
+ System.arraycopy(worldSeed, 0, LAST_SEEN_WORLD_SEED.get(), 0, Globals.WORLD_SEED_LONGS);
+ }
+ return HASHED_WORLD_SEED.get();
+ }
+
+ private void moreRandomBits() {
+ message[3] = counter++;
+ System.arraycopy(getHashedWorldSeed(), 0, randomBits, 0, 8);
+ Hashing.hash(message, randomBits, cachedInternalState, 64, true);
+ }
+
+ private long getBits(int count) {
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX) {
+ moreRandomBits();
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ }
+
+ int alignment = randomBitIndex & 63;
+ if ((randomBitIndex >>> 6) == ((randomBitIndex + count) >>> 6)) {
+ long result = (randomBits[randomBitIndex >>> 6] >>> alignment) & ((1L << count) - 1);
+ randomBitIndex += count;
+ return result;
+ } else {
+ long result = (randomBits[randomBitIndex >>> 6] >>> alignment) & ((1L << (64 - alignment)) - 1);
+ randomBitIndex += count;
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX) {
+ moreRandomBits();
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ }
+ alignment = randomBitIndex & 63;
+ result <<= alignment;
+ result |= (randomBits[randomBitIndex >>> 6] >>> (64 - alignment)) & ((1L << alignment) - 1);
+
+ return result;
+ }
+ }
+
+ @Override
+ public @NotNull RandomSource fork() {
+ WorldgenCryptoRandom fork = new WorldgenCryptoRandom(0, 0, null, 0);
+
+ System.arraycopy(Globals.worldSeed, 0, fork.worldSeed, 0, Globals.WORLD_SEED_LONGS);
+ fork.message[0] = this.message[0];
+ fork.message[1] = this.message[1];
+ fork.message[2] = this.message[2];
+ fork.message[3] = this.message[3];
+ fork.randomBitIndex = this.randomBitIndex;
+ fork.counter = this.counter;
+ fork.nextLong();
+
+ return fork;
+ }
+
+ @Override
+ public int next(int bits) {
+ return (int) getBits(bits);
+ }
+
+ @Override
+ public void consumeCount(int count) {
+ randomBitIndex += count;
+ if (randomBitIndex >= MAX_RANDOM_BIT_INDEX * 2) {
+ randomBitIndex -= MAX_RANDOM_BIT_INDEX;
+ counter += randomBitIndex >>> LOG2_MAX_RANDOM_BIT_INDEX;
+ randomBitIndex &= MAX_RANDOM_BIT_INDEX - 1;
+ randomBitIndex += MAX_RANDOM_BIT_INDEX;
+ }
+ }
+
+ @Override
+ public int nextInt(int bound) {
+ int bits = Mth.ceillog2(bound);
+ int result;
+ do {
+ result = (int) getBits(bits);
+ } while (result >= bound);
+
+ return result;
+ }
+
+ @Override
+ public long nextLong() {
+ return getBits(64);
+ }
+
+ @Override
+ public double nextDouble() {
+ return getBits(53) * 0x1.0p-53;
+ }
+
+ @Override
+ public long setDecorationSeed(long worldSeed, int blockX, int blockZ) {
+ setSecureSeed(blockX, blockZ, Globals.Salt.POPULATION, 0);
+ return ((long) blockX << 32) | ((long) blockZ & 0xffffffffL);
+ }
+
+ @Override
+ public void setFeatureSeed(long populationSeed, int index, int step) {
+ setSecureSeed((int) (populationSeed >> 32), (int) populationSeed, Globals.Salt.DECORATION, index + 10000L * step);
+ }
+
+ @Override
+ public void setLargeFeatureSeed(long worldSeed, int chunkX, int chunkZ) {
+ super.setLargeFeatureSeed(worldSeed, chunkX, chunkZ);
+ }
+
+ @Override
+ public void setLargeFeatureWithSalt(long worldSeed, int regionX, int regionZ, int salt) {
+ super.setLargeFeatureWithSalt(worldSeed, regionX, regionZ, salt);
+ }
+}
\ No newline at end of file

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Fix-MC-2025
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 2d9f75526240689facba1a4fbef7d40ef8299a1d..76f7479798b72cc9219ccb97b5c99e4645ce43d2 100644
index 3700f7c1893e9ccdcef04ae1fab5d7c97c5a91d7..50cd9a50b773a1c10f58a6c0ccbad1b512d1f4f1 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2774,6 +2774,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] FoliaPR Add TPS From Region
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 20cf4ce4f73f681bdbe092d4693812800c953be9..4fe9d348b6f14224d4095dcd8ff0a16a1d61589c 100644
index aecd4c5767a5c91ca60db395b6f412950aa77b26..e8a9351f40fdcd8ea47632677be52308f9f72b5d 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -3105,6 +3105,42 @@ public final class CraftServer implements Server {
@@ -3109,6 +3109,42 @@ public final class CraftServer implements Server {
};
}