From 71455cca647cbc58cf43b9244a2fda2286638779 Mon Sep 17 00:00:00 2001 From: Helvetica Volubi Date: Wed, 18 Jun 2025 16:50:23 +0800 Subject: [PATCH] feat: old replaceable by mushrooms (#10) Update upstream (Luminol) --- gradle.properties | 4 +- .../features/0001-Rebrand-to-Lophine.patch | 315 +++++++++++++++++ .../features/0001-Rebrand-to-Lophine.patch | 8 +- ...-for-command-block-command-execution.patch | 4 +- ...-config-to-disable-end-crystal-check.patch | 4 +- ...04-Add-config-to-enable-tick-command.patch | 18 +- ...05-Add-config-to-revert-raid-changes.patch | 28 +- ...-to-enable-Cross-Region-Damage-trace.patch | 16 +- ...-config-to-enable-Raytracing-tracker.patch | 24 +- ...urpur-Barrels-and-enderchests-6-rows.patch | 22 +- .../0009-Stackable-ShulkerBoxes.patch | 92 ++--- .../features/0010-Better-ShulkerBox.patch | 34 +- .../0011-Spawn-invulnerable-time.patch | 6 +- .../0012-Old-nether-portal-collision.patch | 4 +- .../0013-Old-zombie-reinforcement.patch | 4 +- .../0014-Old-replaceable-by-mushrooms.patch | 38 ++ ...-support.patch => 0015-I18n-support.patch} | 6 +- .../features/0001-Rebrand-to-Lophine.patch | 324 +----------------- ...urpur-Barrels-and-enderchests-6-rows.patch | 6 +- .../tr7zw/entityculling/CullTask.java.patch | 154 --------- .../DefaultChunkDataProvider.java.patch | 45 --- .../versionless/access/Cullable.java.patch | 20 -- .../lophine/config/LophineConfig.java.patch | 36 -- .../experiment/CommandConfig.java.patch | 30 -- .../EntityDamageSourceTraceConfig.java.patch | 25 -- .../RayTrackingEntityTrackerConfig.java.patch | 31 -- .../misc/ContainerExpansionConfig.java.patch | 40 --- .../DisableEndCrystalCheckConfig.java.patch | 26 -- .../modules/misc/OldFeatureConfig.java.patch | 29 -- .../modules/misc/RaidChangesConfig.java.patch | 57 --- .../optimizations/LanguageConfig.java.patch | 25 -- .../modules/removed/RemovedConfig.java.patch | 27 -- .../lophine/utils/ServerI18nUtil.java.patch | 254 -------------- .../lophine/utils/ShulkerBoxesUtil.java.patch | 184 ---------- .../dev/tr7zw/entityculling/CullTask.java | 151 ++++++++ .../DefaultChunkDataProvider.java | 42 +++ .../versionless/access/Cullable.java | 17 + .../fun/bm/lophine/config/LophineConfig.java | 33 ++ .../modules/experiment/CommandConfig.java | 27 ++ .../EntityDamageSourceTraceConfig.java | 22 ++ .../RayTrackingEntityTrackerConfig.java | 28 ++ .../misc/ContainerExpansionConfig.java | 37 ++ .../misc/DisableEndCrystalCheckConfig.java | 23 ++ .../config/modules/misc/OldFeatureConfig.java | 29 ++ .../modules/misc/RaidChangesConfig.java | 54 +++ .../modules/optimizations/LanguageConfig.java | 22 ++ .../config/modules/removed/RemovedConfig.java | 24 ++ .../fun/bm/lophine/utils/ServerI18nUtil.java | 251 ++++++++++++++ .../bm/lophine/utils/ShulkerBoxesUtil.java | 181 ++++++++++ 49 files changed, 1442 insertions(+), 1439 deletions(-) create mode 100644 lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch create mode 100644 lophine-server/minecraft-patches/features/0014-Old-replaceable-by-mushrooms.patch rename lophine-server/minecraft-patches/features/{0014-I18n-support.patch => 0015-I18n-support.patch} (76%) delete mode 100644 lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/CullTask.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/LophineConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java.patch delete mode 100644 lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java.patch create mode 100644 lophine-server/src/main/java/dev/tr7zw/entityculling/CullTask.java create mode 100644 lophine-server/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java create mode 100644 lophine-server/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/LophineConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RaidChangesConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/utils/ServerI18nUtil.java create mode 100644 lophine-server/src/main/java/fun/bm/lophine/utils/ShulkerBoxesUtil.java diff --git a/gradle.properties b/gradle.properties index 3a5fdc0..23b4f4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ -group=me.earthme.lophine +group=fun.bm.lophine version=1.21.5-R0.1-SNAPSHOT mcVersion=1.21.5 -luminolRef=cd8a4e11dce2e85cdef873648e615ae7ca79fd99 +luminolRef=68e8267c24e37f0dcb3b2fb74a4a1aec641014ba org.gradle.configuration-cache=true org.gradle.caching=true diff --git a/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch b/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch new file mode 100644 index 0000000..afbbb56 --- /dev/null +++ b/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch @@ -0,0 +1,315 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Sun, 8 Jun 2025 00:58:13 +0800 +Subject: [PATCH] Rebrand to Lophine + + +diff --git a/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java +index fb63e2a3205ea9f7aaee0ff0f4dc0cc1a5268507..645f2f41de74f4461685c753dcd6cfc5dfa8b2ab 100644 +--- a/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java ++++ b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java +@@ -13,11 +13,17 @@ import java.util.ArrayList; + import java.util.List; + + public class LuminolConfigCommand extends Command { +- public LuminolConfigCommand() { +- super("luminolconfig"); +- this.setPermission("luminol.commands.luminolconfig"); ++ private LuminolConfig config; ++ ++ public LuminolConfigCommand(String name) { ++ super(name + "config"); ++ this.setPermission(name + ".commands." + name + "config"); + this.setDescription("Manage config file"); +- this.setUsage("/luminolconfig"); ++ this.setUsage("/" + name + "config"); ++ } ++ ++ public void initConfig(LuminolConfig config) { ++ this.config = config; + } + + public void wrongUse(CommandSender sender) { +@@ -38,7 +44,7 @@ public class LuminolConfigCommand extends Command { + result.add("reset"); + result.add("reload"); + } else if (args.length == 2 && (args[0].equals("query") || args[0].equals("set") || args[0].equals("reset"))) { +- result.addAll(LuminolConfig.completeConfigPath(args[1])); ++ result.addAll(config.completeConfigPath(args[1])); + } + return result; + } +@@ -59,7 +65,7 @@ public class LuminolConfigCommand extends Command { + + switch (args[0]) { + case "reload" -> { +- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( ++ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( + Component + .text("Reloaded config file!") + .color(TextColor.color(0, 255, 0)) +@@ -69,8 +75,8 @@ public class LuminolConfigCommand extends Command { + if (args.length == 2 || args.length > 3) { + wrongUse(sender); + return true; +- } else if (LuminolConfig.setConfig(args[1], args[2])) { +- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( ++ } else if (config.setConfig(args[1], args[2])) { ++ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( + Component + .text("Set Config " + args[1] + " to " + args[2] + " successfully!") + .color(TextColor.color(0, 255, 0)) +@@ -88,10 +94,10 @@ public class LuminolConfigCommand extends Command { + wrongUse(sender); + return true; + } else { +- LuminolConfig.resetConfig(args[1]); +- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( ++ config.resetConfig(args[1]); ++ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( + Component +- .text("Reset Config " + args[1] + " to " + LuminolConfig.getConfig(args[1]) + " successfully!") ++ .text("Reset Config " + args[1] + " to " + config.getConfig(args[1]) + " successfully!") + .color(TextColor.color(0, 255, 0)) + )); + } +@@ -103,7 +109,7 @@ public class LuminolConfigCommand extends Command { + } else { + sender.sendMessage( + Component +- .text("Config " + args[1] + " is " + LuminolConfig.getConfig(args[1]) + "!") ++ .text("Config " + args[1] + " is " + config.getConfig(args[1]) + "!") + .color(TextColor.color(0, 255, 0)) + ); + } +diff --git a/src/main/java/me/earthme/luminol/config/LuminolConfig.java b/src/main/java/me/earthme/luminol/config/LuminolConfig.java +index 4526eba8e9dfb605bc4672a3eaf0688a5af66049..c05aa7296cd41e21306acd0b8fbc6d6684f56d9a 100644 +--- a/src/main/java/me/earthme/luminol/config/LuminolConfig.java ++++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java +@@ -29,22 +29,33 @@ import java.util.jar.JarEntry; + import java.util.jar.JarFile; + + public class LuminolConfig { +- public static final Logger logger = LogManager.getLogger(); +- private static final File baseConfigFolder = new File("luminol_config"); +- private static final File baseConfigFile = new File(baseConfigFolder, "luminol_global_config.toml"); +- private static final Set allInstanced = new HashSet<>(); +- private static final Map stagedConfigMap = new HashMap<>(); +- private static final Map defaultvalueMap = new HashMap<>(); +- public static boolean alreadyInit = false; +- private static CommentedFileConfig configFileInstance; +- +- public static void setupLatch() { +- Bukkit.getCommandMap().register("luminolconfig", "luminol", new LuminolConfigCommand()); ++ public final Logger logger = LogManager.getLogger(); ++ private final File baseConfigFolder; ++ private final File baseConfigFile; ++ private final String name; ++ private final String pack; ++ private final Set allInstanced = new HashSet<>(); ++ private final Map stagedConfigMap = new HashMap<>(); ++ private final Map defaultvalueMap = new HashMap<>(); ++ public boolean alreadyInit = false; ++ private CommentedFileConfig configFileInstance; ++ ++ public LuminolConfig(@NotNull File base, @NotNull String name, @NotNull String pack) { ++ this.baseConfigFolder = base; ++ this.name = name; ++ this.pack = pack; ++ this.baseConfigFile = new File(base, name + "_global_config.toml"); ++ } ++ ++ public void setupLatch() { ++ LuminolConfigCommand command = new LuminolConfigCommand(name); ++ Bukkit.getCommandMap().register(name + "config", name, command); ++ command.initConfig(this); + alreadyInit = true; + } + +- public static void reload() { +- RegionizedServer.ensureGlobalTickThread("Reload luminol config off global region thread!"); ++ public void reload() { ++ RegionizedServer.ensureGlobalTickThread("Reload " + name + " config off global region thread!"); + + dropAllInstanced(); + try { +@@ -56,8 +67,8 @@ public class LuminolConfig { + } + + @Contract(" -> new") +- public static @NotNull CompletableFuture reloadAsync() { +- return CompletableFuture.runAsync(LuminolConfig::reload, task -> RegionizedServer.getInstance().addTask(() -> { ++ public @NotNull CompletableFuture reloadAsync() { ++ return CompletableFuture.runAsync(this::reload, task -> RegionizedServer.getInstance().addTask(() -> { + try { + task.run(); + } catch (Exception e) { +@@ -66,17 +77,17 @@ public class LuminolConfig { + })); + } + +- public static void dropAllInstanced() { ++ public void dropAllInstanced() { + allInstanced.clear(); + } + +- public static void finalizeLoadConfig() { ++ public void finalizeLoadConfig() { + for (IConfigModule module : allInstanced) { + module.onLoaded(configFileInstance); + } + } + +- public static void preLoadConfig() throws IOException { ++ public void preLoadConfig() throws IOException { + baseConfigFolder.mkdirs(); + + if (!baseConfigFile.exists()) { +@@ -98,21 +109,21 @@ public class LuminolConfig { + saveConfigs(); + } + +- private static void loadAllModules() throws IllegalAccessException { ++ private void loadAllModules() throws IllegalAccessException { + for (IConfigModule instanced : allInstanced) { + loadForSingle(instanced); + } + } + +- private static void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { +- for (Class clazz : getClasses("me.earthme.luminol.config.modules")) { ++ private void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { ++ for (Class clazz : getClasses(pack)) { + if (IConfigModule.class.isAssignableFrom(clazz)) { + allInstanced.add((IConfigModule) clazz.getConstructor().newInstance()); + } + } + } + +- private static void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException { ++ private void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException { + final EnumConfigCategory category = singleConfigModule.getCategory(); + + Field[] fields = singleConfigModule.getClass().getDeclaredFields(); +@@ -203,7 +214,7 @@ public class LuminolConfig { + } + } + +- public static void removeConfig(String name, String[] keys) { ++ public void removeConfig(String name, String[] keys) { + configFileInstance.remove(name); + Object configAtPath = configFileInstance.get(String.join(".", keys)); + if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) { +@@ -211,7 +222,7 @@ public class LuminolConfig { + } + } + +- public static void removeConfig(String[] keys) { ++ public void removeConfig(String[] keys) { + configFileInstance.remove(String.join(".", keys)); + Object configAtPath = configFileInstance.get(String.join(".", Arrays.copyOfRange(keys, 1, keys.length))); + if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) { +@@ -219,11 +230,11 @@ public class LuminolConfig { + } + } + +- public static boolean setConfig(String[] keys, Object value) { ++ public boolean setConfig(String[] keys, Object value) { + return setConfig(String.join(".", keys), value); + } + +- public static boolean setConfig(String key, Object value) { ++ public boolean setConfig(String key, Object value) { + if (configFileInstance.contains(key) && configFileInstance.get(key) != null) { + stagedConfigMap.put(key, value); + return true; +@@ -231,7 +242,7 @@ public class LuminolConfig { + return false; + } + +- private static Object tryTransform(Class targetType, Object value) { ++ private Object tryTransform(Class targetType, Object value) { + if (!targetType.isAssignableFrom(value.getClass())) { + try { + if (targetType == Integer.class) { +@@ -255,27 +266,27 @@ public class LuminolConfig { + return value; + } + +- public static void saveConfigs() { ++ public void saveConfigs() { + configFileInstance.save(); + } + +- public static void resetConfig(String[] keys) { ++ public void resetConfig(String[] keys) { + resetConfig(String.join(".", keys)); + } + +- public static void resetConfig(String key) { ++ public void resetConfig(String key) { + stagedConfigMap.put(key, null); + } + +- public static String getConfig(String[] keys) { ++ public String getConfig(String[] keys) { + return getConfig(String.join(".", keys)); + } + +- public static String getConfig(String key) { ++ public String getConfig(String key) { + return configFileInstance.get(key).toString(); + } + +- public static List completeConfigPath(String partialPath) { ++ public List completeConfigPath(String partialPath) { + List allPaths = getAllConfigPaths(partialPath); + List result = new ArrayList<>(); + +@@ -295,13 +306,13 @@ public class LuminolConfig { + return result; + } + +- private static List getAllConfigPaths(String currentPath) { ++ private List getAllConfigPaths(String currentPath) { + return defaultvalueMap.keySet().stream() + .filter(k -> k.startsWith(currentPath)) + .toList(); + } + +- public static @NotNull Set> getClasses(String pack) { ++ public @NotNull Set> getClasses(String pack) { + Set> classes = new LinkedHashSet<>(); + String packageDirName = pack.replace('.', '/'); + Enumeration dirs; +@@ -332,7 +343,7 @@ public class LuminolConfig { + return classes; + } + +- private static void findClassesInPackageByFile(String packageName, String packagePath, Set> classes) { ++ private void findClassesInPackageByFile(String packageName, String packagePath, Set> classes) { + File dir = new File(packagePath); + + if (!dir.exists() || !dir.isDirectory()) { +@@ -356,7 +367,7 @@ public class LuminolConfig { + } + } + +- private static void findClassesInPackageByJar(String packageName, Enumeration entries, String packageDirName, Set> classes) { ++ private void findClassesInPackageByJar(String packageName, Enumeration entries, String packageDirName, Set> classes) { + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); +diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java +index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 100644 +--- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java ++++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java +@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; + + public class ServerModNameConfig implements IConfigModule { + @ConfigInfo(baseName = "name") +- public static String serverModName = "Luminol"; ++ public static String serverModName = "Lophine"; + + @ConfigInfo(baseName = "vanilla_spoof") + public static boolean fakeVanilla = false; diff --git a/lophine-server/minecraft-patches/features/0001-Rebrand-to-Lophine.patch b/lophine-server/minecraft-patches/features/0001-Rebrand-to-Lophine.patch index 74663a2..40cda06 100644 --- a/lophine-server/minecraft-patches/features/0001-Rebrand-to-Lophine.patch +++ b/lophine-server/minecraft-patches/features/0001-Rebrand-to-Lophine.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand to Lophine diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index fcf599846a38beeb8f094d5376c01d5a690f7a2f..a70c04dc72a15e4e8de8de677951f1eb605057b0 100644 +index fcf599846a38beeb8f094d5376c01d5a690f7a2f..48ef71f32b9aa385a8caecafcc8442f932ef8470 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java @@ -108,7 +108,7 @@ public class Main { @@ -13,12 +13,12 @@ index fcf599846a38beeb8f094d5376c01d5a690f7a2f..a70c04dc72a15e4e8de8de677951f1eb } - me.earthme.luminol.config.LuminolConfig.preLoadConfig(); // Luminol - Luminol config -+ me.earthme.lophine.config.LophineConfig.initConfigs(); // Lophine - Lophine config ++ fun.bm.lophine.config.LophineConfig.initConfigs(); // Lophine - Lophine config io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper Bootstrap.bootStrap(); Bootstrap.validate(); diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 5290b9cb524160717fb40704fb10fc0d0a37941b..ba0cdba050cd3bf9231e15dd9543d34f37d9dae5 100644 +index 5290b9cb524160717fb40704fb10fc0d0a37941b..1b60378cdbf5bc88f996010a61cceec7c2b9e2dc 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java @@ -171,8 +171,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @@ -27,7 +27,7 @@ index 5290b9cb524160717fb40704fb10fc0d0a37941b..ba0cdba050cd3bf9231e15dd9543d34f // Paper end - initialize global and world-defaults configuration - me.earthme.luminol.config.LuminolConfig.finalizeLoadConfig(); //Luminol - load config file - me.earthme.luminol.config.LuminolConfig.setupLatch(); //Luminol - load config file -+ me.earthme.lophine.config.LophineConfig.loadConfigFiles(); //Luminol - load config file // Lophine - load config file ++ fun.bm.lophine.config.LophineConfig.loadConfigFiles(); //Luminol - load config file // Lophine - load config file if (false) this.server.spark.enableEarlyIfRequested(); // Paper - spark // Luminol - Force disable builtin spark // Paper start - fix converting txt to json file; convert old users earlier after PlayerList creation but before file load/save if (this.convertOldUsers()) { diff --git a/lophine-server/minecraft-patches/features/0002-Add-config-for-command-block-command-execution.patch b/lophine-server/minecraft-patches/features/0002-Add-config-for-command-block-command-execution.patch index 5a2642f..6fbeddb 100644 --- a/lophine-server/minecraft-patches/features/0002-Add-config-for-command-block-command-execution.patch +++ b/lophine-server/minecraft-patches/features/0002-Add-config-for-command-block-command-execution.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add config for command block command execution diff --git a/net/minecraft/world/level/BaseCommandBlock.java b/net/minecraft/world/level/BaseCommandBlock.java -index 91e30f9c83259abc0589f4ee69c429cd4305d6ea..8155da15908fd944d452fd6aaff69cfdfcc7b36b 100644 +index 91e30f9c83259abc0589f4ee69c429cd4305d6ea..e1cc5576017358849e7c536accd14d2e6eb5c706 100644 --- a/net/minecraft/world/level/BaseCommandBlock.java +++ b/net/minecraft/world/level/BaseCommandBlock.java @@ -102,7 +102,7 @@ public abstract class BaseCommandBlock implements CommandSource { @@ -13,7 +13,7 @@ index 91e30f9c83259abc0589f4ee69c429cd4305d6ea..8155da15908fd944d452fd6aaff69cfd public boolean performCommand(Level level) { - if (true) return false; // Folia - region threading -+ if (!me.earthme.lophine.config.modules.experiment.CommandConfig.block) return false; // Folia - region threading // Luminol ++ if (!fun.bm.lophine.config.modules.experiment.CommandConfig.block) return false; // Folia - region threading // Luminol if (level.isClientSide || level.getGameTime() == this.lastExecution) { return false; } else if ("Searge".equalsIgnoreCase(this.command)) { diff --git a/lophine-server/minecraft-patches/features/0003-Add-config-to-disable-end-crystal-check.patch b/lophine-server/minecraft-patches/features/0003-Add-config-to-disable-end-crystal-check.patch index 9b4dd34..93753fe 100644 --- a/lophine-server/minecraft-patches/features/0003-Add-config-to-disable-end-crystal-check.patch +++ b/lophine-server/minecraft-patches/features/0003-Add-config-to-disable-end-crystal-check.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add config to disable end crystal check diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..d62a9e93dae7b4a7a079e73e80e68e6a81b4c437 100644 +index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..4fb9244172b74c3c5fed984d5d3b968f76dd12be 100644 --- a/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java @@ -547,6 +547,8 @@ public class EndDragonFight { @@ -13,7 +13,7 @@ index 4fa8371c212dcc02b8cf5fd267b736e1cf3f50c1..d62a9e93dae7b4a7a079e73e80e68e6a blockPos = this.portalLocation; } + // Luminol start - Disable end crystal check -+ if (!me.earthme.lophine.config.modules.misc.DisableEndCrystalCheckConfig.disableCheck) { ++ if (!fun.bm.lophine.config.modules.misc.DisableEndCrystalCheckConfig.disableCheck) { // Paper start - Perf: Do crystal-portal proximity check before entity lookup if (placedEndCrystalPos != null) { // The end crystal must be 0 or 1 higher than the portal origin diff --git a/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-tick-command.patch b/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-tick-command.patch index a96ff0a..d799cca 100644 --- a/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-tick-command.patch +++ b/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-tick-command.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable tick command diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java -index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530c547ac19 100644 +index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..acdc5dbc34071dc4342f17fab0d483d775c9044d 100644 --- a/io/papermc/paper/threadedregions/RegionizedServer.java +++ b/io/papermc/paper/threadedregions/RegionizedServer.java @@ -299,6 +299,11 @@ public final class RegionizedServer { @@ -13,7 +13,7 @@ index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530 */ ++this.tickCount; + // Luminol start - Add a config to enable tick command -+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) { ++ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) { + MinecraftServer.tickRateManager.tick(); + } + // Luminol end - Add a config to enable tick command @@ -25,7 +25,7 @@ index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530 } + // Luminol start - Add a config to enable tick command -+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) { ++ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) { + MinecraftServer.tickRateManager.reduceSprintTicks(); + MinecraftServer.tickRateManager.endTickWork(); + } @@ -39,12 +39,12 @@ index 8e91ec81128bdbd5f78e1f04fe17bcbd6e5dc280..6b4a33189b4dcd4979fb421248f72530 private void tickTime(final ServerLevel world, final int tickCount) { - if (world.tickTime) { -+ if ((!me.earthme.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command ++ if ((!fun.bm.lophine.config.modules.experiment.CommandConfig.tick || world.tickRateManager().runsNormally()) && world.tickTime) { // Luminol - Add a config to enable tick command if (world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { world.setDayTime(world.levelData.getDayTime() + (long)tickCount); } diff --git a/io/papermc/paper/threadedregions/TickRegionScheduler.java b/io/papermc/paper/threadedregions/TickRegionScheduler.java -index 0357792de0ed8ec9058d1847c8b45c33ff365af6..0bb3752d361bda347646dab5dc83bcf6bd5e717f 100644 +index 0357792de0ed8ec9058d1847c8b45c33ff365af6..4945c11f573a53df2f5be4beb7af6a3f4d32f7d4 100644 --- a/io/papermc/paper/threadedregions/TickRegionScheduler.java +++ b/io/papermc/paper/threadedregions/TickRegionScheduler.java @@ -31,8 +31,8 @@ public final class TickRegionScheduler { @@ -66,7 +66,7 @@ index 0357792de0ed8ec9058d1847c8b45c33ff365af6..0bb3752d361bda347646dab5dc83bcf6 - final int tickCount = Math.max(1, this.tickSchedule.getPeriodsAhead(TIME_BETWEEN_TICKS, tickStart)); + // Luminol start - Add a config to enable tick command + final int tickCount; -+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) { ++ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) { + if (MinecraftServer.tickRateManager.isSprinting() && MinecraftServer.tickRateManager.checkShouldSprintThisTick()) { + TICK_RATE = net.minecraft.server.commands.TickCommand.MAX_TICKRATE; + TIME_BETWEEN_TICKS = (long) (1_000_000_000L / TICK_RATE); @@ -89,7 +89,7 @@ index 0357792de0ed8ec9058d1847c8b45c33ff365af6..0bb3752d361bda347646dab5dc83bcf6 // next start isn't updated until the end of this tick this.tickRegion(tickCount, tickStart, scheduledEnd); + // Luminol start - Add a config to enable tick command -+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) { ++ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) { + MinecraftServer.tickRateManager.endTickWork(); + } + // Luminol end - Add a config to enable tick command @@ -97,7 +97,7 @@ index 0357792de0ed8ec9058d1847c8b45c33ff365af6..0bb3752d361bda347646dab5dc83bcf6 this.scheduler.regionFailed(this, false, thr); // regionFailed will schedule a shutdown, so we should avoid letting this region tick further diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java -index ea50e3c0c4044f03dc8257680814f808fbf3a177..bd5d8bbb667585c1bf976e2eaa38f2b72eabe9e2 100644 +index ea50e3c0c4044f03dc8257680814f808fbf3a177..63154426854c507738d646490ac76f531145fab2 100644 --- a/net/minecraft/commands/Commands.java +++ b/net/minecraft/commands/Commands.java @@ -214,7 +214,11 @@ public class Commands { @@ -106,7 +106,7 @@ index ea50e3c0c4044f03dc8257680814f808fbf3a177..bd5d8bbb667585c1bf976e2eaa38f2b7 //TestCommand.register(this.dispatcher, context); // Folia - region threading - //TickCommand.register(this.dispatcher); // Folia - region threading - TODO later + // Luminol start - Add a config to enable tick command -+ if (me.earthme.lophine.config.modules.experiment.CommandConfig.tick) { ++ if (fun.bm.lophine.config.modules.experiment.CommandConfig.tick) { + TickCommand.register(this.dispatcher); // Folia - region threading - TODO later + } + // Luminol end - Add a config to enable tick command diff --git a/lophine-server/minecraft-patches/features/0005-Add-config-to-revert-raid-changes.patch b/lophine-server/minecraft-patches/features/0005-Add-config-to-revert-raid-changes.patch index a9ae0b3..45e8778 100644 --- a/lophine-server/minecraft-patches/features/0005-Add-config-to-revert-raid-changes.patch +++ b/lophine-server/minecraft-patches/features/0005-Add-config-to-revert-raid-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add config to revert raid changes diff --git a/net/minecraft/world/effect/BadOmenMobEffect.java b/net/minecraft/world/effect/BadOmenMobEffect.java -index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc353bdb99b 100644 +index 80f17f33f670018240c854df589cf90cdeab6e70..985f27d249810bf133a520d937b7006e57f553ec 100644 --- a/net/minecraft/world/effect/BadOmenMobEffect.java +++ b/net/minecraft/world/effect/BadOmenMobEffect.java @@ -22,6 +22,11 @@ class BadOmenMobEffect extends MobEffect { @@ -13,7 +13,7 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc3 && level.getDifficulty() != Difficulty.PEACEFUL && level.isVillage(serverPlayer.blockPosition())) { + // Leaves start - Revert raid changes -+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.trigger) { ++ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.trigger) { + return level.getRaids().createOrExtendRaid(serverPlayer, serverPlayer.blockPosition()) == null; + } + // Leaves end - Revert raid changes @@ -21,7 +21,7 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..faf31ef66ab7fcdb4135e4c225312dc3 if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) { serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier)); diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java -index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e032e6add8 100644 +index dbb207c638a64b733dc21704033ff55ca1f44f1d..bcafacb6fce19212e99a3f04e0356b34304d92f1 100644 --- a/net/minecraft/world/entity/raid/Raid.java +++ b/net/minecraft/world/entity/raid/Raid.java @@ -340,7 +340,20 @@ public class Raid { @@ -30,7 +30,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0 if (flag1) { - this.waveSpawnPos = this.getValidSpawnPos(level); + // Luminol Start - Raid revert -+ if (!me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert) { ++ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) { + this.waveSpawnPos = this.getValidSpawnPos(level); + } else { + int n4 = 0; @@ -53,7 +53,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0 - BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20)); + // Luminol Start - Raid revert + BlockPos blockPos; -+ if (!me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert) { ++ if (!fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert) { + blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20)); + } else { + blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(level, i, 20); @@ -67,7 +67,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0 } - if (i > 5) { -+ if (i > (me.earthme.lophine.config.modules.misc.RaidChangesConfig.posRevert ? 3 : 5)) { // Luminol - Raid revert ++ if (i > (fun.bm.lophine.config.modules.misc.RaidChangesConfig.posRevert ? 3 : 5)) { // Luminol - Raid revert org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit this.stop(); break; @@ -94,7 +94,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0 int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f); int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3); - if (Mth.abs(height - this.center.getY()) <= 96) { -+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.heightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - Disable height check ++ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.heightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - Disable height check mutableBlockPos.set(i2, height, i3); if (!level.isVillage(mutableBlockPos) || i <= 7) { int i4 = 10; @@ -126,7 +126,7 @@ index dbb207c638a64b733dc21704033ff55ca1f44f1d..94fdf1b5ce2622e4e654d09562f8a3e0 // Folia start - make raids thread-safe if (!this.ownsRaid(level)) { diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e022e52843 100644 +index f6f36c15120da6c57c0cbea3743a0819252cb6cc..3ab6288dc1903da0aaf93ed8b5d9848e4fe663f1 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java @@ -127,6 +127,41 @@ public abstract class Raider extends PatrollingMonster { @@ -135,7 +135,7 @@ index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e0 } + + // Leaves start - Revert raid changes -+ if (me.earthme.lophine.config.modules.misc.RaidChangesConfig.effect && !this.hasRaid()) { ++ if (fun.bm.lophine.config.modules.misc.RaidChangesConfig.effect && !this.hasRaid()) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); + net.minecraft.world.entity.player.Player entityhuman = null; + if (entity instanceof net.minecraft.world.entity.player.Player player) { @@ -159,7 +159,7 @@ index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e0 + } + + i = net.minecraft.util.Mth.clamp(i, 0, 4); -+ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true); ++ net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true); + + if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) { + entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit @@ -176,12 +176,12 @@ index f6f36c15120da6c57c0cbea3743a0819252cb6cc..b2bb9b0ff94a7e463ebc4e59fe4378e0 public boolean hasRaid() { - return this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null); -+ return !me.earthme.lophine.config.modules.misc.RaidChangesConfig.selfCheck && (this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null)); // Leaves - Disable raid self check ++ return !fun.bm.lophine.config.modules.misc.RaidChangesConfig.selfCheck && (this.level() instanceof ServerLevel serverLevel && (this.getCurrentRaid() != null || serverLevel.getRaidAt(this.blockPosition()) != null)); // Leaves - Disable raid self check } public boolean hasActiveRaid() { diff --git a/net/minecraft/world/item/component/OminousBottleAmplifier.java b/net/minecraft/world/item/component/OminousBottleAmplifier.java -index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73db6943b04 100644 +index 33907bb190ffa22ccf9ea424b1e536297878711a..2fca459f2c888079322f6b957bbee3ac0e33c4bc 100644 --- a/net/minecraft/world/item/component/OminousBottleAmplifier.java +++ b/net/minecraft/world/item/component/OminousBottleAmplifier.java @@ -29,7 +29,7 @@ public record OminousBottleAmplifier(int value) implements ConsumableListener, T @@ -189,7 +189,7 @@ index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73d @Override public void onConsume(Level level, LivingEntity entity, ItemStack stack, Consumable consumable) { - entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below -+ entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below // Luminol - Raid effect infinite ++ entity.addEffect(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Paper - properly resend entities - diff on change for below // Luminol - Raid effect infinite } // Paper start - properly resend entities - collect packets for bundle @@ -198,7 +198,7 @@ index 33907bb190ffa22ccf9ea424b1e536297878711a..4b48aa0db9c1ab3e6227d1e1a42ce73d @Override public void addToTooltip(Item.TooltipContext context, Consumer tooltipAdder, TooltipFlag flag, DataComponentGetter componentGetter) { - List list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, 120000, this.value, false, false, true)); -+ List list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Luminol - Raid effect infinite ++ List list = List.of(new MobEffectInstance(MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, this.value, false, false, true)); // Luminol - Raid effect infinite PotionContents.addPotionTooltip(list, tooltipAdder, 1.0F, context.tickRate()); } } diff --git a/lophine-server/minecraft-patches/features/0006-Add-config-to-enable-Cross-Region-Damage-trace.patch b/lophine-server/minecraft-patches/features/0006-Add-config-to-enable-Cross-Region-Damage-trace.patch index 9782609..e1eca48 100644 --- a/lophine-server/minecraft-patches/features/0006-Add-config-to-enable-Cross-Region-Damage-trace.patch +++ b/lophine-server/minecraft-patches/features/0006-Add-config-to-enable-Cross-Region-Damage-trace.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable Cross Region Damage trace diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b492f79102 100644 +index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..a4eeb75eeb1cd69c60cd1c273f23f9744837148f 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -1330,6 +1330,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -13,7 +13,7 @@ index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b4 killCredit.awardKillScore(this, cause); this.createWitherRose(killCredit); + // Luminol Start - Cross Region Damage trace -+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { ++ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { + final LivingEntity entitylivingnew = this.getKillCreditOrigin(); + if (entitylivingnew != null) { + this.damageTransferToAsync(entitylivingnew, cause); @@ -48,7 +48,7 @@ index c3201cb0ba6f928f658d4c74a1ef2b7e8900b1f6..1764875b9024569671bf2be537afb8b4 AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); this.level() diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a20ea8a351 100644 +index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..f5a1b2711a4eb910decb26b26c57ebfa7cedb231 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -1191,6 +1191,29 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -59,7 +59,7 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2 + public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent, boolean async) { + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) { + return addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); -+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { ++ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { + postToEntityThreadAddEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); + return true; + } @@ -86,7 +86,7 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2 if (killer != null) { killer.awardKillScore(this, damageSource); + // Luminol Start - Cross Region Damage trace -+ } else if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { ++ } else if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { + final LivingEntity killernew = this.getKillCreditOrigin(); + if (killernew != null) { + this.damageTransferToAsync(killernew, damageSource); @@ -134,15 +134,15 @@ index 5b5e63c4dc10076ba33a8ddf0ebae96643b1161f..063d682ae6cde044717a32402785b7a2 return (float)this.getAttributeValue(Attributes.MAX_HEALTH); } diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index b2bb9b0ff94a7e463ebc4e59fe4378e022e52843..4b72db3350f2990b00076fffb9df811560db8207 100644 +index 3ab6288dc1903da0aaf93ed8b5d9848e4fe663f1..61eab8abd59914a7bf613393059ec039bab1b8ee 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java @@ -156,7 +156,13 @@ public abstract class Raider extends PatrollingMonster { - net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, me.earthme.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true); + net.minecraft.world.effect.MobEffectInstance mobeffect1 = new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.BAD_OMEN, fun.bm.lophine.config.modules.misc.RaidChangesConfig.infinite ? net.minecraft.world.effect.MobEffectInstance.INFINITE_DURATION : 120000, i, false, false, true); if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_DISABLE_RAIDS)) { - entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true); // CraftBukkit -+ if (me.earthme.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { ++ if (fun.bm.lophine.config.modules.experiment.EntityDamageSourceTraceConfig.enabled) { + // Luminol start - Raid changes adapt DamageSource trace + entityhuman.addEffect(mobeffect1, entityhuman, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN, true, true); + } else { diff --git a/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-Raytracing-tracker.patch b/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-Raytracing-tracker.patch index b645ee4..65643bf 100644 --- a/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-Raytracing-tracker.patch +++ b/lophine-server/minecraft-patches/features/0007-Add-config-to-enable-Raytracing-tracker.patch @@ -18,7 +18,7 @@ index ee53f78396f4377d3e5c2998826f231208066ef6..607091ecbd4a7261f2c0d839ee4dd1d2 double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1); if (rangeY != -1) { diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf58e93876 100644 +index a023cc399fc8bfee7771e5ca6716578f89b7072f..88ce4001a2fa764a4dc41ca0132ad067d40d3d03 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -59,7 +59,7 @@ index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf + + @Override + public boolean isCulled() { -+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) ++ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) + return false; + return this.culled; + } @@ -71,7 +71,7 @@ index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf + + @Override + public boolean isOutOfCamera() { -+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) ++ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) + return false; + return this.outOfCamera; + } @@ -92,7 +92,7 @@ index 6b72ab233508e6df1eca34360ce76d102ee25a41..f39ee4605cc15102d6560afd1dad5f56 public EntityType( EntityType.EntityFactory factory, diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..34c4c195519de03ec11897160b98c80353eb3d6c 100644 +index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..a26ec6f1a1553bf0b415f382177c75f481e21180 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -220,6 +220,25 @@ public abstract class Player extends LivingEntity { @@ -102,18 +102,18 @@ index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..34c4c195519de03ec11897160b98c803 + // Luminol start - Raytracing entity tracker + public dev.tr7zw.entityculling.CullTask cullTask; + { -+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) { ++ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) { + this.cullTask = null; + }else { + final com.logisticscraft.occlusionculling.OcclusionCullingInstance culling = new com.logisticscraft.occlusionculling.OcclusionCullingInstance( -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance, ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance, + new dev.tr7zw.entityculling.DefaultChunkDataProvider(this.level()) + ); + + this.cullTask = new dev.tr7zw.entityculling.CullTask( + culling, this, -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit, -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit, ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs + ); + } + } @@ -126,19 +126,19 @@ index 543750bee43bfaaaf33f2cec53eb0de05e7a1dd2..34c4c195519de03ec11897160b98c803 @Override public void tick() { + // Luminol start - Ray tracing entity tracker -+ if (!me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) { ++ if (!fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.enabled) { + if (this.cullTask != null) this.cullTask.signalStop(); + this.cullTask = null; + }else { + final com.logisticscraft.occlusionculling.OcclusionCullingInstance culling = new com.logisticscraft.occlusionculling.OcclusionCullingInstance( -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance, ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.tracingDistance, + new dev.tr7zw.entityculling.DefaultChunkDataProvider(this.level()) + ); + + this.cullTask = new dev.tr7zw.entityculling.CullTask( + culling, this, -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit, -+ me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.hitboxLimit, ++ fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig.checkIntervalMs + ); + } + if (this.cullTask != null) this.cullTask.setup(); diff --git a/lophine-server/minecraft-patches/features/0008-Purpur-Barrels-and-enderchests-6-rows.patch b/lophine-server/minecraft-patches/features/0008-Purpur-Barrels-and-enderchests-6-rows.patch index 9113184..3b3f734 100644 --- a/lophine-server/minecraft-patches/features/0008-Purpur-Barrels-and-enderchests-6-rows.patch +++ b/lophine-server/minecraft-patches/features/0008-Purpur-Barrels-and-enderchests-6-rows.patch @@ -8,7 +8,7 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18 Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE) diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 001483b7098523f3645a95c81fcf0e38b551705e..3a83ba2fab530e9e64d53167d296c1f2ca1b9e4b 100644 +index 001483b7098523f3645a95c81fcf0e38b551705e..70be6c3ef009f1746353cc330a188bc693174ed7 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -1116,6 +1116,10 @@ public abstract class PlayerList { @@ -17,13 +17,13 @@ index 001483b7098523f3645a95c81fcf0e38b551705e..3a83ba2fab530e9e64d53167d296c1f2 } // Paper - Add sendOpLevel API + + // Purpur start - Barrels and enderchests 6 rows -+ player.enderChestSlotCount = me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27; ++ player.enderChestSlotCount = fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27; + // Purpur end - Barrels and enderchests 6 rows } public boolean isWhiteListed(GameProfile profile) { diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 34c4c195519de03ec11897160b98c80353eb3d6c..27e335e01d8f09f05a4fea5f15407dbe3a4555cb 100644 +index a26ec6f1a1553bf0b415f382177c75f481e21180..1f7a97b0a52461108fe5a17d2ecc224b1a9f26a1 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -210,6 +210,7 @@ public abstract class Player extends LivingEntity { @@ -70,7 +70,7 @@ index 0fffa384f928ab84451331380968fb4650eafe26..d84a10396395939149da88bcb01be59e return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6); } diff --git a/net/minecraft/world/inventory/PlayerEnderChestContainer.java b/net/minecraft/world/inventory/PlayerEnderChestContainer.java -index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08ecef44f02 100644 +index bc2b95973192069fc64581b59583b19df876f55d..89a2f0286b9ab036f4412a9d657c0105382ed64f 100644 --- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java +++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java @@ -25,11 +25,18 @@ public class PlayerEnderChestContainer extends SimpleContainer { @@ -78,7 +78,7 @@ index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08e public PlayerEnderChestContainer(Player owner) { - super(27); -+ super(me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27); ++ super(fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows < 7 && fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows > 0 ? 9 * fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows : 27); this.owner = owner; // CraftBukkit end } @@ -94,7 +94,7 @@ index bc2b95973192069fc64581b59583b19df876f55d..d80a3760c0a84df19d0b2063c648f08e this.activeChest = enderChestBlockEntity; } diff --git a/net/minecraft/world/level/block/EnderChestBlock.java b/net/minecraft/world/level/block/EnderChestBlock.java -index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b15a4c40c 100644 +index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..fe374f08b7829b846b2a1c2ac3ca500ca3e48684 100644 --- a/net/minecraft/world/level/block/EnderChestBlock.java +++ b/net/minecraft/world/level/block/EnderChestBlock.java @@ -85,8 +85,14 @@ public class EnderChestBlock extends AbstractChestBlock i @@ -103,7 +103,7 @@ index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b new SimpleMenuProvider( - (containerId, playerInventory, player1) -> ChestMenu.threeRows(containerId, playerInventory, enderChestInventory), CONTAINER_TITLE - ) -+ (containerId, playerInventory, player1) -> switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) { ++ (containerId, playerInventory, player1) -> switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) { + case 6 -> ChestMenu.sixRows(containerId, playerInventory, enderChestInventory); + case 5 -> ChestMenu.fiveRows(containerId, playerInventory, enderChestInventory); + case 4 -> ChestMenu.fourRows(containerId, playerInventory, enderChestInventory); @@ -115,7 +115,7 @@ index 5077a9ff7b78801bdc53536a37aee07b8d86ee4d..c7866aa9a3647d3285eb0996fbc55e1b // Paper end - Fix InventoryOpenEvent cancellation - moved up; player.awardStat(Stats.OPEN_ENDERCHEST); diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff0695914e7b6e3 100644 +index 027502d0af5512c31878978c4d05c52fa3029cca..e05239582477157bd530222704bf43b1254c63ca 100644 --- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java @@ -56,7 +56,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @@ -124,7 +124,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959 - private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); + // Purpur start - Barrels and enderchests 6 rows -+ private NonNullList items = NonNullList.withSize(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { ++ private NonNullList items = NonNullList.withSize(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { + case 6 -> 54; + case 5 -> 45; + case 4 -> 36; @@ -143,7 +143,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959 public int getContainerSize() { - return 27; + // Purpur start - Barrels and enderchests 6 rows -+ return switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { ++ return switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { + case 6 -> 54; + case 5 -> 45; + case 4 -> 36; @@ -161,7 +161,7 @@ index 027502d0af5512c31878978c4d05c52fa3029cca..4716015da322ed1f41c9f81d5ff06959 protected AbstractContainerMenu createMenu(int id, Inventory player) { - return ChestMenu.threeRows(id, player, this); + // Purpur start - Barrels and enderchests 6 rows -+ return switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { ++ return switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { + case 6 -> ChestMenu.sixRows(id, player, this); + case 5 -> ChestMenu.fiveRows(id, player, this); + case 4 -> ChestMenu.fourRows(id, player, this); diff --git a/lophine-server/minecraft-patches/features/0009-Stackable-ShulkerBoxes.patch b/lophine-server/minecraft-patches/features/0009-Stackable-ShulkerBoxes.patch index 1261b19..3ef283a 100644 --- a/lophine-server/minecraft-patches/features/0009-Stackable-ShulkerBoxes.patch +++ b/lophine-server/minecraft-patches/features/0009-Stackable-ShulkerBoxes.patch @@ -8,7 +8,7 @@ Some of changes is a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/9 Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) diff --git a/net/minecraft/commands/arguments/item/ItemInput.java b/net/minecraft/commands/arguments/item/ItemInput.java -index 643797124fe5a4489d0b7419b7e600c04f283ef2..3c0d01d444210029b6380417c6ee0e6408f89c18 100644 +index 643797124fe5a4489d0b7419b7e600c04f283ef2..3b4d97c76db9c742072c92dd7c8b39553c62a1f1 100644 --- a/net/minecraft/commands/arguments/item/ItemInput.java +++ b/net/minecraft/commands/arguments/item/ItemInput.java @@ -39,8 +39,9 @@ public class ItemInput { @@ -17,14 +17,14 @@ index 643797124fe5a4489d0b7419b7e600c04f283ef2..3c0d01d444210029b6380417c6ee0e64 itemStack.applyComponents(this.components); - if (allowOversizedStacks && count > itemStack.getMaxStackSize()) { - throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize()); -+ int maxCount = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes ++ int maxCount = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes + if (allowOversizedStacks && count > maxCount) { // Lophine - Stackable ShulkerBoxes + throw ERROR_STACK_TOO_BIG.create(this.getItemName(), maxCount); // Lophine - Stackable ShulkerBoxes } else { return itemStack; } diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java -index c1c0dea9f5ac3101c2f12714c8dd460457d45cb7..f94fc39297caebd0cb14d7b71c865f13b5c3b17c 100644 +index f06753a8fa1138fa165de0a8367e04d79eaad381..267d9d2532302a7fb4ba55e8920dbb8891b2c232 100644 --- a/net/minecraft/server/commands/GiveCommand.java +++ b/net/minecraft/server/commands/GiveCommand.java @@ -52,7 +52,7 @@ public class GiveCommand { @@ -32,12 +32,12 @@ index c1c0dea9f5ac3101c2f12714c8dd460457d45cb7..f94fc39297caebd0cb14d7b71c865f13 ItemStack itemStack = item.createItemStack(1, false); final Component displayName = itemStack.getDisplayName(); // Paper - get display name early - int maxStackSize = itemStack.getMaxStackSize(); -+ int maxStackSize = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes ++ int maxStackSize = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes int i = maxStackSize * 100; if (count > i) { source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName())); diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c61a70377 100644 +index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..a726ce12ecac55912606c4a1958b5afa07c491bc 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -3056,7 +3056,7 @@ public class ServerGamePacketListenerImpl @@ -45,7 +45,7 @@ index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) { int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1; - toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); -+ toPlace = Math.min(toPlace, me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(clickedItem) - clickedItem.getCount()); // Lophine - Stackable ShulkerBoxes ++ toPlace = Math.min(toPlace, fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(clickedItem) - clickedItem.getCount()); // Lophine - Stackable ShulkerBoxes toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); if (toPlace == 1) { action = InventoryAction.PLACE_ONE; @@ -54,7 +54,7 @@ index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c } else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) { if (clickedItem.getCount() >= 0) { - if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { -+ if (clickedItem.getCount() + cursor.getCount() <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(cursor)) { // Lophine - Stackable ShulkerBoxes ++ if (clickedItem.getCount() + cursor.getCount() <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(cursor)) { // Lophine - Stackable ShulkerBoxes // As of 1.5, this is result slots only action = InventoryAction.PICKUP_ALL; } @@ -62,7 +62,7 @@ index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c this.player.containerMenu.broadcastFullState(); } else { this.player.containerMenu.broadcastChanges(); -+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes ++ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes } if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. } @@ -71,7 +71,7 @@ index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45; - boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize(); -+ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes ++ boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Lophine - Stackable ShulkerBoxes if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot // CraftBukkit start - Call click event org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView(); @@ -79,12 +79,12 @@ index 4fc3c9f2b04711569c12a0efa027601fdd0a40b5..e1e68cc934f8b5a8606a553f3e0a939c this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack); this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack); this.player.inventoryMenu.broadcastChanges(); -+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes ++ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck()) this.player.containerMenu.broadcastCarriedItem(); // Lophine - Stackable ShulkerBoxes if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. } else if (flag && flag2) { if (this.dropSpamThrottler.isUnderThreshold()) { diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java -index b382665cc125b8b5c0938e5e55984e4bf91d37ff..8ff16372df12f07e47d81fe45ad7270bb5c2b052 100644 +index b382665cc125b8b5c0938e5e55984e4bf91d37ff..5d8bd05f966cf9befe8b8f3359b2fa4ce2428e98 100644 --- a/net/minecraft/world/Container.java +++ b/net/minecraft/world/Container.java @@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable { @@ -93,7 +93,7 @@ index b382665cc125b8b5c0938e5e55984e4bf91d37ff..8ff16372df12f07e47d81fe45ad7270b + // Leaves start - stackable shulker boxes + default int getMaxStackLeaves(ItemStack stack) { -+ return Math.min(this.getMaxStackSize(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); ++ return Math.min(this.getMaxStackSize(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); + } + // Leaves end - stackable shulker boxes + @@ -123,7 +123,7 @@ index 133e042371bcf84f1935903ec57d204e3b7abd84..201599988e20219b6a99bf1594ad6c0c if (min > 0) { other.grow(min); diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8be93ad0d7 100644 +index a9cc35b4b253d9a7fd90f811af9be629b164fad0..1e0c8a256b9602a56f607274e93208bf5b04ee0d 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java @@ -281,10 +281,45 @@ public class ItemEntity extends Entity implements TraceableEntity { @@ -131,20 +131,20 @@ index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8b private boolean isMergable() { ItemStack item = this.getItem(); - return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate -+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item); // Paper - Alternative item-despawn-rate // Lophine - Stackable ShulkerBoxes ++ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item); // Paper - Alternative item-despawn-rate // Lophine - Stackable ShulkerBoxes + } + + // Lophine start - Stackable ShulkerBoxes + private boolean tryMergeShulkerBox(ItemEntity ote) { + ItemStack sf = this.getItem(); + ItemStack ot = ote.getItem(); -+ if (!me.earthme.lophine.utils.ShulkerBoxesUtil.checkShulkerBox(sf)) return false; ++ if (!fun.bm.lophine.utils.ShulkerBoxesUtil.checkShulkerBox(sf)) return false; + if (sf.getItem().equals(ot.getItem()) -+ && me.earthme.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(sf) -+ && me.earthme.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(ot) ++ && fun.bm.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(sf) ++ && fun.bm.lophine.utils.ShulkerBoxesUtil.emptyShulkerBoxCheck(ot) + && Objects.equals(sf.getComponents(), ot.getComponents()) // empty block entity tags are cleaned up when spawning -+ && sf.getCount() != me.earthme.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe()) { -+ int count = Math.min(ot.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe() - sf.getCount()); ++ && sf.getCount() != fun.bm.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe()) { ++ int count = Math.min(ot.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getShulkerBoxesMaxCountUnsafe() - sf.getCount()); + sf.grow(count); + this.setItem(sf); + @@ -165,7 +165,7 @@ index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8b private void tryToMerge(ItemEntity itemEntity) { + // Lophine start - Stackable ShulkerBoxes -+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck() ++ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck() + && this.tryMergeShulkerBox(itemEntity)) { + return; + } @@ -174,7 +174,7 @@ index a9cc35b4b253d9a7fd90f811af9be629b164fad0..5c548cb30565d156c6eeb316b0c0ce8b ItemStack item1 = itemEntity.getItem(); if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a6138651e7f9a7 100644 +index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9020f7c83e5bd19e9a9d3748d200ce5772a9cefa 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java @@ -149,8 +149,8 @@ public class Inventory implements Container, Nameable { @@ -183,8 +183,8 @@ index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a61386 return !destination.isEmpty() - && destination.isStackable() - && destination.getCount() < this.getMaxStackSize(destination) -+ && me.earthme.lophine.utils.ShulkerBoxesUtil.isStackable(destination) // Lophine - Stackable ShulkerBoxes -+ && destination.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(destination) // Lophine - Stackable ShulkerBoxes ++ && fun.bm.lophine.utils.ShulkerBoxesUtil.isStackable(destination) // Lophine - Stackable ShulkerBoxes ++ && destination.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(destination) // Lophine - Stackable ShulkerBoxes && ItemStack.isSameItemSameComponents(destination, origin); // Paper - check if itemstack is stackable first } @@ -193,7 +193,7 @@ index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a61386 if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) { - remains -= (itemInSlot.getMaxStackSize() < this.getMaxStackSize() ? itemInSlot.getMaxStackSize() : this.getMaxStackSize()) - itemInSlot.getCount(); -+ remains -= (me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) < this.getMaxStackSize() ? me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Lophine - Stackable ShulkerBoxes ++ remains -= (fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) < this.getMaxStackSize() ? fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInSlot) : this.getMaxStackSize()) - itemInSlot.getCount(); // Lophine - Stackable ShulkerBoxes } if (remains <= 0) { return itemStack.getCount(); @@ -202,7 +202,7 @@ index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a61386 ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND); if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) { - remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount(); -+ remains -= (me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) < this.getMaxStackSize() ? me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Lophine - Stackable ShulkerBoxes ++ remains -= (fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) < this.getMaxStackSize() ? fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Lophine - Stackable ShulkerBoxes } if (remains <= 0) { return itemStack.getCount(); @@ -220,12 +220,12 @@ index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..9fbd605df26d388c01d2ed9ca6a61386 } - int i = stack.getMaxStackSize() - this.getItem(slotWithRemainingSpace).getCount(); -+ int i = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Lophine - Stackable ShulkerBoxes ++ int i = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) - this.getItem(slotWithRemainingSpace).getCount(); // Lophine - Stackable ShulkerBoxes if (this.add(slotWithRemainingSpace, stack.split(i)) && sendPacket && this.player instanceof ServerPlayer serverPlayer) { serverPlayer.connection.send(this.createInventoryUpdatePacket(slotWithRemainingSpace)); } diff --git a/net/minecraft/world/entity/player/StackedItemContents.java b/net/minecraft/world/entity/player/StackedItemContents.java -index 83ccde54c625d40dc595e000c533f60aa929bd5a..16e9ac7449761c1427a528be60e964ef737ce897 100644 +index 83ccde54c625d40dc595e000c533f60aa929bd5a..3206b599481eeab29c58bc1ca9cac6935da9963a 100644 --- a/net/minecraft/world/entity/player/StackedItemContents.java +++ b/net/minecraft/world/entity/player/StackedItemContents.java @@ -23,7 +23,7 @@ public class StackedItemContents { @@ -233,7 +233,7 @@ index 83ccde54c625d40dc595e000c533f60aa929bd5a..16e9ac7449761c1427a528be60e964ef public void accountStack(ItemStack stack) { - this.accountStack(stack, stack.getMaxStackSize()); -+ this.accountStack(stack, me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable Shulker Boxes ++ this.accountStack(stack, fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable Shulker Boxes } public void accountStack(ItemStack stack, int maxStackSize) { @@ -251,7 +251,7 @@ index feebd1610ebd3c26a337259c14f5c774dc72b937..7df6ff842e41763aec2d88d1f8a5f750 default SlotAccess getChestVehicleSlot(final int index) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93e882e756 100644 +index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..45ff5b9a50bdec611f7c1aa4cb77fb0b13b6910c 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -234,6 +234,14 @@ public abstract class AbstractContainerMenu { @@ -274,7 +274,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 && this.canDragTo(slot1)) { int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0; - int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack)); -+ int min = Math.min(me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Lophine - Stackable ShulkerBoxes ++ int min = Math.min(fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack), slot1.getMaxStackSize(itemStack)); // Lophine - Stackable ShulkerBoxes int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min); count -= min1 - i2; // slot1.setByPlayer(itemStack.copyWithCount(min1)); @@ -283,7 +283,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 } } else if (ItemStack.isSameItemSameComponents(carried, carried2)) { - Optional optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player); -+ Optional optional1 = slot.tryRemove(carried.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(carried2) - carried2.getCount(), player); // Lophine - Stackable ShulkerBoxes ++ Optional optional1 = slot.tryRemove(carried.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(carried2) - carried2.getCount(), player); // Lophine - Stackable ShulkerBoxes optional1.ifPresent(itemStack2 -> { carried2.grow(itemStack2.getCount()); slot.onTake(player, itemStack2); @@ -292,7 +292,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 if (slot2.hasItem()) { ItemStack itemStack = slot2.getItem(); - this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize())); -+ this.setCarried(itemStack.copyWithCount(me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack))); // Lophine - Stackable ShulkerBoxes ++ this.setCarried(itemStack.copyWithCount(fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack))); // Lophine - Stackable ShulkerBoxes } } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { Slot slot2 = this.slots.get(slotId); @@ -301,7 +301,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 for (int i3 = 0; i3 < 2; i3++) { - for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < itemStack.getMaxStackSize(); i4 += maxStackSize) { -+ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); i4 += maxStackSize) { // Lophine - Stackable ShulkerBoxes ++ for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); i4 += maxStackSize) { // Lophine - Stackable ShulkerBoxes Slot slot3 = this.slots.get(i4); if (slot3.hasItem() && canItemQuickReplace(slot3, itemStack, true) @@ -310,8 +310,8 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 ItemStack item1 = slot3.getItem(); - if (i3 != 0 || item1.getCount() != item1.getMaxStackSize()) { - ItemStack itemStack1 = slot3.safeTake(item1.getCount(), itemStack.getMaxStackSize() - itemStack.getCount(), player); -+ if (i3 != 0 || item1.getCount() != me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item1)) { // Lophine - stackable shulker boxes -+ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack) - itemStack.getCount(), player); // Lophine - stackable shulker boxes ++ if (i3 != 0 || item1.getCount() != fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(item1)) { // Lophine - stackable shulker boxes ++ ItemStack itemStack1 = slot3.safeTake(item1.getCount(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack) - itemStack.getCount(), player); // Lophine - stackable shulker boxes itemStack.grow(itemStack1.getCount()); } } @@ -320,7 +320,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 } - if (stack.isStackable()) { -+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.isStackable(stack)) { // Lophine - Stackable ShulkerBoxes ++ if (fun.bm.lophine.utils.ShulkerBoxesUtil.isStackable(stack)) { // Lophine - Stackable ShulkerBoxes while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { Slot slot = this.slots.get(i); ItemStack item = slot.getItem(); @@ -329,7 +329,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 boolean flag = slot == null || !slot.hasItem(); return !flag && ItemStack.isSameItemSameComponents(stack, slot.getItem()) - ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize() -+ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) // Lophine - Stackable ShulkerBoxes ++ ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack) // Lophine - Stackable ShulkerBoxes : flag; } @@ -338,7 +338,7 @@ index a9cf0ef95b706f05060bbcd2a4f5a03c60f783d2..6c5a01b065c7daa37219a8ab2a471d93 case 0 -> Mth.floor((float)stack.getCount() / slots.size()); case 1 -> 1; - case 2 -> stack.getMaxStackSize(); -+ case 2 -> me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack); // Lophine - Stackable ShulkerBoxes ++ case 2 -> fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack); // Lophine - Stackable ShulkerBoxes default -> stack.getCount(); }; } @@ -365,7 +365,7 @@ index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..cf87267130c0aebd38206556261929d6 this.updateSellItem(); } diff --git a/net/minecraft/world/inventory/Slot.java b/net/minecraft/world/inventory/Slot.java -index 5ceb8964476b40db4511bec91ff13c4f522a1357..170353b8d1d330e54d9836e78ba2d41d023e0f51 100644 +index 5ceb8964476b40db4511bec91ff13c4f522a1357..dd978d1590fb896775a240ed87e38d85744017d3 100644 --- a/net/minecraft/world/inventory/Slot.java +++ b/net/minecraft/world/inventory/Slot.java @@ -75,7 +75,7 @@ public class Slot { @@ -373,12 +373,12 @@ index 5ceb8964476b40db4511bec91ff13c4f522a1357..170353b8d1d330e54d9836e78ba2d41d public int getMaxStackSize(ItemStack stack) { - return Math.min(this.getMaxStackSize(), stack.getMaxStackSize()); -+ return Math.min(this.getMaxStackSize(), me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable ShulkerBoxes ++ return Math.min(this.getMaxStackSize(), fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(stack)); // Lophine - Stackable ShulkerBoxes } @Nullable diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f282c6bd2 100644 +index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..9ea26913cbaa7571a107b421614380e2755f4430 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java @@ -165,7 +165,7 @@ public final class ItemStack implements DataComponentHolder { @@ -396,7 +396,7 @@ index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f DataComponentPatch dataComponentPatch = codec.decode(buffer); - return new ItemStack(holder, varInt, dataComponentPatch); + ItemStack itemStack = new ItemStack(holder, varInt, dataComponentPatch); -+ return me.earthme.lophine.utils.ShulkerBoxesUtil.decodeMaxStackSize(itemStack); ++ return fun.bm.lophine.utils.ShulkerBoxesUtil.decodeMaxStackSize(itemStack); } } @@ -407,7 +407,7 @@ index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f - buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count - Item.STREAM_CODEC.encode(buffer, value.getItemHolder()); + // Leaves start - stackable shulker boxes -+ final ItemStack itemStack = me.earthme.lophine.utils.ShulkerBoxesUtil.encodeMaxStackSize(value.copy()); ++ final ItemStack itemStack = fun.bm.lophine.utils.ShulkerBoxesUtil.encodeMaxStackSize(value.copy()); + buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count + Item.STREAM_CODEC.encode(buffer, itemStack.getItemHolder()); // Paper start - adventure; conditionally render translatable components @@ -425,12 +425,12 @@ index 09455150810e4fb6e4637fdb9e2e8a30fe0bc247..5d2571d0199a25087954b4e67bc7551f for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) { int count = itemStack.getCount(); - int maxStackSize = itemStack.getMaxStackSize(); -+ int maxStackSize = me.earthme.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Leaves - stackable shulker boxes ++ int maxStackSize = fun.bm.lophine.utils.ShulkerBoxesUtil.getItemMaxCount(itemStack); // Leaves - stackable shulker boxes if (count > maxStackSize) { return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize); } diff --git a/net/minecraft/world/level/block/AbstractCauldronBlock.java b/net/minecraft/world/level/block/AbstractCauldronBlock.java -index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..ee0315ff52914666e3e3cfc38f726512e3301986 100644 +index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..3e3d516ff62f49a3cc00375d173af137b555d515 100644 --- a/net/minecraft/world/level/block/AbstractCauldronBlock.java +++ b/net/minecraft/world/level/block/AbstractCauldronBlock.java @@ -62,9 +62,27 @@ public abstract class AbstractCauldronBlock extends Block { @@ -444,7 +444,7 @@ index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..ee0315ff52914666e3e3cfc38f726512 + // Leaves start - stackable shulker boxes + private InteractionResult wrapInteractor(CauldronInteraction cauldronBehavior, BlockState blockState, Level world, BlockPos blockPos, Player playerEntity, InteractionHand hand, ItemStack itemStack, net.minecraft.core.Direction hitDirection) { + int count = -1; -+ if (me.earthme.lophine.utils.ShulkerBoxesUtil.shouldCheck() && itemStack.getItem() instanceof net.minecraft.world.item.BlockItem bi && ++ if (fun.bm.lophine.utils.ShulkerBoxesUtil.shouldCheck() && itemStack.getItem() instanceof net.minecraft.world.item.BlockItem bi && + bi.getBlock() instanceof ShulkerBoxBlock) { + count = itemStack.getCount(); + } diff --git a/lophine-server/minecraft-patches/features/0010-Better-ShulkerBox.patch b/lophine-server/minecraft-patches/features/0010-Better-ShulkerBox.patch index 3412226..d215e85 100644 --- a/lophine-server/minecraft-patches/features/0010-Better-ShulkerBox.patch +++ b/lophine-server/minecraft-patches/features/0010-Better-ShulkerBox.patch @@ -6,19 +6,19 @@ Subject: [PATCH] Better ShulkerBox You can open shulker box with shift & right click diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 1764875b9024569671bf2be537afb8b492f79102..b395482c6b5609c3b878f4e1ed17861b3b3fe9f7 100644 +index a4eeb75eeb1cd69c60cd1c273f23f9744837148f..5596214edb14d30c9ed5af4ffdcdd2041d135c6d 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -2351,6 +2351,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.containerMenu.removed(this); this.inventoryMenu.transferState(this.containerMenu); this.containerMenu = this.inventoryMenu; -+ me.earthme.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box ++ fun.bm.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box } @Override diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index 9fbd605df26d388c01d2ed9ca6a6138651e7f9a7..075526ce459cee3b157d5338ec079ad1515c6640 100644 +index 9020f7c83e5bd19e9a9d3748d200ce5772a9cefa..8138eb8ce2184ade08b4244dbd150ec264387f7a 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java @@ -470,6 +470,15 @@ public class Inventory implements Container, Nameable { @@ -26,11 +26,11 @@ index 9fbd605df26d388c01d2ed9ca6a6138651e7f9a7..075526ce459cee3b157d5338ec079ad1 this.equipment.set(equipmentSlot, stack); } + // Lophine start - better shulker box -+ if (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker) { ++ if (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker) { + boolean isMainHand = index == selected; + boolean isOffHand = index == 40; + if (isMainHand || isOffHand) { -+ me.earthme.lophine.utils.ShulkerBoxesUtil.inventoryCallBack(isMainHand, this.player); ++ fun.bm.lophine.utils.ShulkerBoxesUtil.inventoryCallBack(isMainHand, this.player); + } + } + // Lophine end - better shulker box @@ -38,25 +38,25 @@ index 9fbd605df26d388c01d2ed9ca6a6138651e7f9a7..075526ce459cee3b157d5338ec079ad1 public ListTag save(ListTag listTag) { diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 27e335e01d8f09f05a4fea5f15407dbe3a4555cb..b1389af2c04527fbc8f62577fad4bc679506a0e9 100644 +index 1f7a97b0a52461108fe5a17d2ecc224b1a9f26a1..86854467df17cc72e48360a0f19a4bbe4aaba3e8 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -595,11 +595,13 @@ public abstract class Player extends LivingEntity { // Paper start - special close for unloaded inventory public void closeUnloadedInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { this.containerMenu = this.inventoryMenu; -+ me.earthme.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box ++ fun.bm.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box } // Paper end - special close for unloaded inventory public void closeContainer() { this.containerMenu = this.inventoryMenu; -+ me.earthme.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box ++ fun.bm.lophine.utils.ShulkerBoxesUtil.clearMap(this); // Lophine - better shulker box } protected void doCloseContainer() { diff --git a/net/minecraft/world/inventory/ShulkerBoxMenu.java b/net/minecraft/world/inventory/ShulkerBoxMenu.java -index 903025c659e6a9423224fe65973696405c69ec6a..e850b533d89f95d01a3b9d265a70845793e37bd7 100644 +index 903025c659e6a9423224fe65973696405c69ec6a..eb20f83d5aa2c06f60c3941e8a54434737c017c4 100644 --- a/net/minecraft/world/inventory/ShulkerBoxMenu.java +++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java @@ -53,7 +53,7 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { @@ -64,12 +64,12 @@ index 903025c659e6a9423224fe65973696405c69ec6a..e850b533d89f95d01a3b9d265a708457 @Override public boolean stillValid(Player player) { - if (!this.checkReachable) return true; // CraftBukkit -+ if (!this.checkReachable || me.earthme.lophine.utils.ShulkerBoxesUtil.checkIfValid(player)) return true; // CraftBukkit // Lophine - better shulker box ++ if (!this.checkReachable || fun.bm.lophine.utils.ShulkerBoxesUtil.checkIfValid(player)) return true; // CraftBukkit // Lophine - better shulker box return this.container.stillValid(player); } diff --git a/net/minecraft/world/item/Item.java b/net/minecraft/world/item/Item.java -index c52fb17d1e496a91223b7387cacb128c1865caee..86d43c4e81dfe9775400e09ae706d4e9cc640bd8 100644 +index c52fb17d1e496a91223b7387cacb128c1865caee..af070f075b1b6523040a4ff29ef37c730af28427 100644 --- a/net/minecraft/world/item/Item.java +++ b/net/minecraft/world/item/Item.java @@ -187,6 +187,13 @@ public class Item implements FeatureElement, ItemLike { @@ -77,10 +77,10 @@ index c52fb17d1e496a91223b7387cacb128c1865caee..86d43c4e81dfe9775400e09ae706d4e9 return InteractionResult.CONSUME; } else { + // Lophine start - better shulker box -+ if (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker ++ if (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker + && player.isShiftKeyDown() -+ && me.earthme.lophine.utils.ShulkerBoxesUtil.checkIfCanOpen(itemInHand)) { -+ me.earthme.lophine.utils.ShulkerBoxesUtil.openShulkerBox(player, itemInHand, hand); ++ && fun.bm.lophine.utils.ShulkerBoxesUtil.checkIfCanOpen(itemInHand)) { ++ fun.bm.lophine.utils.ShulkerBoxesUtil.openShulkerBox(player, itemInHand, hand); + } + // Lophine end - better shulker box return InteractionResult.PASS; @@ -100,7 +100,7 @@ index ecf794f94177fc7b6df483516d920719fbc6fa43..4fda59a4c17009a0009f3d3c13258f4f throw new IllegalArgumentException("Got " + items.size() + " items, but maximum is 256"); } else { diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index 87ebdb6deb66662a38b3eec0dae27eaf859ecabb..7e97f0e200e7fd83aa9504a5fced83d2d00e0319 100644 +index 87ebdb6deb66662a38b3eec0dae27eaf859ecabb..ecf15ffc37e65a469bc33406559bfbd122fe810c 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java @@ -46,6 +46,11 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl @@ -122,8 +122,8 @@ index 87ebdb6deb66662a38b3eec0dae27eaf859ecabb..7e97f0e200e7fd83aa9504a5fced83d2 + // Lophine start - better shulker box + public void setItem(int index, ItemStack stack) { + super.setItem(index, stack); -+ if (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker && !haveRealBlock) { -+ me.earthme.lophine.utils.ShulkerBoxesUtil.shulkerBoxEntityCallBack(this); ++ if (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.betterShulker && !haveRealBlock) { ++ fun.bm.lophine.utils.ShulkerBoxesUtil.shulkerBoxEntityCallBack(this); + } + } + // Lophine end - better shulker box diff --git a/lophine-server/minecraft-patches/features/0011-Spawn-invulnerable-time.patch b/lophine-server/minecraft-patches/features/0011-Spawn-invulnerable-time.patch index 2588a23..9a4adc2 100644 --- a/lophine-server/minecraft-patches/features/0011-Spawn-invulnerable-time.patch +++ b/lophine-server/minecraft-patches/features/0011-Spawn-invulnerable-time.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Spawn invulnerable time diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 1764875b9024569671bf2be537afb8b492f79102..473f9de0908d3fb2cfb640ff7c6f7b78c1280721 100644 +index 5596214edb14d30c9ed5af4ffdcdd2041d135c6d..1a02b14cb457ba8e8c84ec1b111d3829a9c0209c 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -221,6 +221,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -20,7 +20,7 @@ index 1764875b9024569671bf2be537afb8b492f79102..473f9de0908d3fb2cfb640ff7c6f7b78 this.tickClientLoadTimeout(); this.gameMode.tick(); this.wardenSpawnTracker.tick(); -+ if (me.earthme.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime && this.invulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time ++ if (fun.bm.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime && this.invulnerableTime > 0) --this.spawnInvulnerableTime; // Lophine - spawn invulnerable time if (this.invulnerableTime > 0) { this.invulnerableTime--; } @@ -29,7 +29,7 @@ index 1764875b9024569671bf2be537afb8b492f79102..473f9de0908d3fb2cfb640ff7c6f7b78 return false; } else { + // Lophine start - spawn invulnerable time -+ if (me.earthme.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime) { ++ if (fun.bm.lophine.config.modules.misc.OldFeatureConfig.spawnInvulnerableTime) { + if (this.spawnInvulnerableTime > 0 && !damageSource.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } diff --git a/lophine-server/minecraft-patches/features/0012-Old-nether-portal-collision.patch b/lophine-server/minecraft-patches/features/0012-Old-nether-portal-collision.patch index acc94cd..e1a8948 100644 --- a/lophine-server/minecraft-patches/features/0012-Old-nether-portal-collision.patch +++ b/lophine-server/minecraft-patches/features/0012-Old-nether-portal-collision.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Old nether portal collision This patch should removed in 1.21.6 when mojang revert it. diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java -index 421ea9c748159ac989900427a13abe9b244dc7aa..ecdecf0484137e0f98bf41d09e0dc7dc7715fd35 100644 +index 421ea9c748159ac989900427a13abe9b244dc7aa..a5a220e6d41c992d1db8617069aa00eddcf7b95a 100644 --- a/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/net/minecraft/world/level/block/NetherPortalBlock.java @@ -65,7 +65,7 @@ public class NetherPortalBlock extends Block implements Portal { @@ -14,7 +14,7 @@ index 421ea9c748159ac989900427a13abe9b244dc7aa..ecdecf0484137e0f98bf41d09e0dc7dc @Override protected VoxelShape getEntityInsideCollisionShape(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { - return state.getShape(level, pos); -+ return me.earthme.lophine.config.modules.misc.OldFeatureConfig.oldNetherPortalCollision ? Shapes.block() : state.getShape(level, pos); // Lophine - Old nether portal collision ++ return fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldNetherPortalCollision ? Shapes.block() : state.getShape(level, pos); // Lophine - Old nether portal collision } @Override diff --git a/lophine-server/minecraft-patches/features/0013-Old-zombie-reinforcement.patch b/lophine-server/minecraft-patches/features/0013-Old-zombie-reinforcement.patch index df5630e..4729f6a 100644 --- a/lophine-server/minecraft-patches/features/0013-Old-zombie-reinforcement.patch +++ b/lophine-server/minecraft-patches/features/0013-Old-zombie-reinforcement.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Old zombie reinforcement diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index 4395947fc8c719864ac2afde5e6bbb53da5129c2..348e2b6020de8584b512ec849a5fba484380930e 100644 +index 4395947fc8c719864ac2afde5e6bbb53da5129c2..f2b2859084bcff3a004d9b4bfac1f51e75970d39 100644 --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java @@ -342,7 +342,7 @@ public class Zombie extends Monster { @@ -13,7 +13,7 @@ index 4395947fc8c719864ac2afde5e6bbb53da5129c2..348e2b6020de8584b512ec849a5fba48 int floor1 = Mth.floor(this.getY()); int floor2 = Mth.floor(this.getZ()); - EntityType type = this.getType(); -+ EntityType type = me.earthme.lophine.config.modules.misc.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement ++ EntityType type = fun.bm.lophine.config.modules.misc.OldFeatureConfig.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Lophine - old zombie reinforcement Zombie zombie = type.create(level, EntitySpawnReason.REINFORCEMENT); if (zombie == null) { return true; diff --git a/lophine-server/minecraft-patches/features/0014-Old-replaceable-by-mushrooms.patch b/lophine-server/minecraft-patches/features/0014-Old-replaceable-by-mushrooms.patch new file mode 100644 index 0000000..ca0d9fe --- /dev/null +++ b/lophine-server/minecraft-patches/features/0014-Old-replaceable-by-mushrooms.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Wed, 18 Jun 2025 14:24:54 +0800 +Subject: [PATCH] Old replaceable by mushrooms + + +diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java +index 834e27ef2f7b342b074ff9e1e390e02f3ca1c399..f5765e3bbf9e735d6f959e1bf6ee1846ee11b4e9 100644 +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -770,6 +770,14 @@ public abstract class BlockBehaviour implements FeatureElement { + return this.solidRender; + } + ++ public boolean mushroomCheck(BlockState state) { ++ BlockState blockState = state.asState(); ++ if (blockState.canOcclude()) { ++ return !Block.isShapeFullBlock(blockState.getOcclusionShape()); ++ } ++ return true; ++ } ++ + public final boolean canOcclude() { // Paper - Perf: Final for inlining + return this.canOcclude; + } +diff --git a/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java b/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java +index 3a37d66ab3c27c9abd60f35ef3bf3a93f8d7c3cd..2aad65d76cdd0800ac593a5bb3ce84ad1925eab0 100644 +--- a/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java ++++ b/net/minecraft/world/level/levelgen/feature/AbstractHugeMushroomFeature.java +@@ -26,7 +26,7 @@ public abstract class AbstractHugeMushroomFeature extends Feature { -- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( -+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( - Component - .text("Reloaded config file!") - .color(TextColor.color(0, 255, 0)) -@@ -69,8 +75,8 @@ public class LuminolConfigCommand extends Command { - if (args.length == 2 || args.length > 3) { - wrongUse(sender); - return true; -- } else if (LuminolConfig.setConfig(args[1], args[2])) { -- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( -+ } else if (config.setConfig(args[1], args[2])) { -+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( - Component - .text("Set Config " + args[1] + " to " + args[2] + " successfully!") - .color(TextColor.color(0, 255, 0)) -@@ -88,10 +94,10 @@ public class LuminolConfigCommand extends Command { - wrongUse(sender); - return true; - } else { -- LuminolConfig.resetConfig(args[1]); -- LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage( -+ config.resetConfig(args[1]); -+ config.reloadAsync().thenAccept(nullValue -> sender.sendMessage( - Component -- .text("Reset Config " + args[1] + " to " + LuminolConfig.getConfig(args[1]) + " successfully!") -+ .text("Reset Config " + args[1] + " to " + config.getConfig(args[1]) + " successfully!") - .color(TextColor.color(0, 255, 0)) - )); - } -@@ -103,7 +109,7 @@ public class LuminolConfigCommand extends Command { - } else { - sender.sendMessage( - Component -- .text("Config " + args[1] + " is " + LuminolConfig.getConfig(args[1]) + "!") -+ .text("Config " + args[1] + " is " + config.getConfig(args[1]) + "!") - .color(TextColor.color(0, 255, 0)) - ); - } -diff --git a/src/main/java/me/earthme/luminol/config/LuminolConfig.java b/src/main/java/me/earthme/luminol/config/LuminolConfig.java -index 57b1f606d2f4197e1f68d367bf63e04ce2fe1534..01f109fc02590d22a42676f35f23ae72ed08ac36 100644 ---- a/src/main/java/me/earthme/luminol/config/LuminolConfig.java -+++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java -@@ -29,22 +29,33 @@ import java.util.jar.JarEntry; - import java.util.jar.JarFile; - - public class LuminolConfig { -- public static final Logger logger = LogManager.getLogger(); -- private static final File baseConfigFolder = new File("luminol_config"); -- private static final File baseConfigFile = new File(baseConfigFolder, "luminol_global_config.toml"); -- private static final Set allInstanced = new HashSet<>(); -- private static final Map stagedConfigMap = new HashMap<>(); -- private static final Map defaultvalueMap = new HashMap<>(); -- public static boolean alreadyInit = false; -- private static CommentedFileConfig configFileInstance; -- -- public static void setupLatch() { -- Bukkit.getCommandMap().register("luminolconfig", "luminol", new LuminolConfigCommand()); -+ public final Logger logger = LogManager.getLogger(); -+ private final File baseConfigFolder; -+ private final File baseConfigFile; -+ private final String name; -+ private final String pack; -+ private final Set allInstanced = new HashSet<>(); -+ private final Map stagedConfigMap = new HashMap<>(); -+ private final Map defaultvalueMap = new HashMap<>(); -+ public boolean alreadyInit = false; -+ private CommentedFileConfig configFileInstance; -+ -+ public LuminolConfig(@NotNull File base, @NotNull String name, @NotNull String pack) { -+ this.baseConfigFolder = base; -+ this.name = name; -+ this.pack = pack; -+ this.baseConfigFile = new File(base, name + "_global_config.toml"); -+ } -+ -+ public void setupLatch() { -+ LuminolConfigCommand command = new LuminolConfigCommand(name); -+ Bukkit.getCommandMap().register(name + "config", name, command); -+ command.initConfig(this); - alreadyInit = true; - } - -- public static void reload() { -- RegionizedServer.ensureGlobalTickThread("Reload luminol config off global region thread!"); -+ public void reload() { -+ RegionizedServer.ensureGlobalTickThread("Reload " + name + " config off global region thread!"); - - dropAllInstanced(); - try { -@@ -56,8 +67,8 @@ public class LuminolConfig { - } - - @Contract(" -> new") -- public static @NotNull CompletableFuture reloadAsync() { -- return CompletableFuture.runAsync(LuminolConfig::reload, task -> RegionizedServer.getInstance().addTask(() -> { -+ public @NotNull CompletableFuture reloadAsync() { -+ return CompletableFuture.runAsync(this::reload, task -> RegionizedServer.getInstance().addTask(() -> { - try { - task.run(); - } catch (Exception e) { -@@ -66,17 +77,17 @@ public class LuminolConfig { - })); - } - -- public static void dropAllInstanced() { -+ public void dropAllInstanced() { - allInstanced.clear(); - } - -- public static void finalizeLoadConfig() { -+ public void finalizeLoadConfig() { - for (IConfigModule module : allInstanced) { - module.onLoaded(configFileInstance); - } - } - -- public static void preLoadConfig() throws IOException { -+ public void preLoadConfig() throws IOException { - baseConfigFolder.mkdirs(); - - if (!baseConfigFile.exists()) { -@@ -98,21 +109,21 @@ public class LuminolConfig { - saveConfigs(); - } - -- private static void loadAllModules() throws IllegalAccessException { -+ private void loadAllModules() throws IllegalAccessException { - for (IConfigModule instanced : allInstanced) { - loadForSingle(instanced); - } - } - -- private static void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { -- for (Class clazz : getClasses("me.earthme.luminol.config.modules")) { -+ private void instanceAllModule() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { -+ for (Class clazz : getClasses(pack)) { - if (IConfigModule.class.isAssignableFrom(clazz)) { - allInstanced.add((IConfigModule) clazz.getConstructor().newInstance()); - } - } - } - -- private static void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException { -+ private void loadForSingle(@NotNull IConfigModule singleConfigModule) throws IllegalAccessException { - final EnumConfigCategory category = singleConfigModule.getCategory(); - - Field[] fields = singleConfigModule.getClass().getDeclaredFields(); -@@ -203,7 +214,7 @@ public class LuminolConfig { - } - } - -- public static void removeConfig(String name, String[] keys) { -+ public void removeConfig(String name, String[] keys) { - configFileInstance.remove(name); - Object configAtPath = configFileInstance.get(String.join(".", keys)); - if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) { -@@ -211,7 +222,7 @@ public class LuminolConfig { - } - } - -- public static void removeConfig(String[] keys) { -+ public void removeConfig(String[] keys) { - configFileInstance.remove(String.join(".", keys)); - Object configAtPath = configFileInstance.get(String.join(".", Arrays.copyOfRange(keys, 1, keys.length))); - if (configAtPath instanceof UnmodifiableConfig && ((UnmodifiableConfig) configAtPath).isEmpty()) { -@@ -219,11 +230,11 @@ public class LuminolConfig { - } - } - -- public static boolean setConfig(String[] keys, Object value) { -+ public boolean setConfig(String[] keys, Object value) { - return setConfig(String.join(".", keys), value); - } - -- public static boolean setConfig(String key, Object value) { -+ public boolean setConfig(String key, Object value) { - if (configFileInstance.contains(key) && configFileInstance.get(key) != null) { - stagedConfigMap.put(key, value); - return true; -@@ -231,7 +242,7 @@ public class LuminolConfig { - return false; - } - -- private static Object tryTransform(Class targetType, Object value) { -+ private Object tryTransform(Class targetType, Object value) { - if (!targetType.isAssignableFrom(value.getClass())) { - try { - if (targetType == Integer.class) { -@@ -255,27 +266,27 @@ public class LuminolConfig { - return value; - } - -- public static void saveConfigs() { -+ public void saveConfigs() { - configFileInstance.save(); - } - -- public static void resetConfig(String[] keys) { -+ public void resetConfig(String[] keys) { - resetConfig(String.join(".", keys)); - } - -- public static void resetConfig(String key) { -+ public void resetConfig(String key) { - stagedConfigMap.put(key, null); - } - -- public static String getConfig(String[] keys) { -+ public String getConfig(String[] keys) { - return getConfig(String.join(".", keys)); - } - -- public static String getConfig(String key) { -+ public String getConfig(String key) { - return configFileInstance.get(key).toString(); - } - -- public static List completeConfigPath(String partialPath) { -+ public List completeConfigPath(String partialPath) { - List allPaths = getAllConfigPaths(partialPath); - List result = new ArrayList<>(); - -@@ -295,13 +306,13 @@ public class LuminolConfig { - return result; - } - -- private static List getAllConfigPaths(String currentPath) { -+ private List getAllConfigPaths(String currentPath) { - return defaultvalueMap.keySet().stream() - .filter(k -> k.startsWith(currentPath)) - .toList(); - } - -- public static @NotNull Set> getClasses(String pack) { -+ public @NotNull Set> getClasses(String pack) { - Set> classes = new LinkedHashSet<>(); - String packageDirName = pack.replace('.', '/'); - Enumeration dirs; -@@ -332,7 +343,7 @@ public class LuminolConfig { - return classes; - } - -- private static void findClassesInPackageByFile(String packageName, String packagePath, Set> classes) { -+ private void findClassesInPackageByFile(String packageName, String packagePath, Set> classes) { - File dir = new File(packagePath); - - if (!dir.exists() || !dir.isDirectory()) { -@@ -356,7 +367,7 @@ public class LuminolConfig { - } - } - -- private static void findClassesInPackageByJar(String packageName, Enumeration entries, String packageDirName, Set> classes) { -+ private void findClassesInPackageByJar(String packageName, Enumeration entries, String packageDirName, Set> classes) { - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - String name = entry.getName(); -diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java -index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 100644 ---- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java -+++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java -@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; - - public class ServerModNameConfig implements IConfigModule { - @ConfigInfo(baseName = "name") -- public static String serverModName = "Luminol"; -+ public static String serverModName = "Lophine"; - - @ConfigInfo(baseName = "vanilla_spoof") - public static boolean fakeVanilla = false; diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..1c3b94a2592cff74924cf9b355e30b0fa182b79b 100644 +index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..2c546d470013d4daf3ddf427ab4bda1b51d6e641 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java @@ -11,7 +11,7 @@ public final class Versioning { @@ -407,7 +99,7 @@ index 9699d7dcca5cf67f50ad05c0e875de424a4e00c5..1c3b94a2592cff74924cf9b355e30b0f String result = "Unknown-Version"; - InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.luminol/luminol-api/pom.properties"); // Folia //Luminol -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.earthme.lophine/lophine-api/pom.properties"); // Folia //Luminol ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/fun.bm.lophine/lophine-api/pom.properties"); // Folia //Luminol Properties properties = new Properties(); if (stream != null) { diff --git a/lophine-server/paper-patches/features/0002-Purpur-Barrels-and-enderchests-6-rows.patch b/lophine-server/paper-patches/features/0002-Purpur-Barrels-and-enderchests-6-rows.patch index 0bb6b79..3d3e711 100644 --- a/lophine-server/paper-patches/features/0002-Purpur-Barrels-and-enderchests-6-rows.patch +++ b/lophine-server/paper-patches/features/0002-Purpur-Barrels-and-enderchests-6-rows.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Purpur-Barrels-and-enderchests-6-rows diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index c00ddfe41439954fa0fd87c0933f274c8a752eb6..ac0218fcdf9e9c77a30b7f09b2a5e557ef0f7591 100644 +index c00ddfe41439954fa0fd87c0933f274c8a752eb6..77aa23d252e429e01bc7bd8c47e23d12ca596fdb 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -150,9 +150,26 @@ public class CraftContainer extends AbstractContainerMenu { @@ -15,7 +15,7 @@ index c00ddfe41439954fa0fd87c0933f274c8a752eb6..ac0218fcdf9e9c77a30b7f09b2a5e557 - case BARREL: - this.delegate = new ChestMenu(net.minecraft.world.inventory.MenuType.GENERIC_9x3, windowId, bottom, top, top.getContainerSize() / 9); + // Purpur start - Barrels and enderchests 6 rows -+ this.delegate = new ChestMenu(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) { ++ this.delegate = new ChestMenu(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.enderchestRows) { + case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6; + case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5; + case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4; @@ -25,7 +25,7 @@ index c00ddfe41439954fa0fd87c0933f274c8a752eb6..ac0218fcdf9e9c77a30b7f09b2a5e557 + }, windowId, bottom, top, top.getContainerSize() / 9); break; + case BARREL: -+ this.delegate = new ChestMenu(switch (me.earthme.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { ++ this.delegate = new ChestMenu(switch (fun.bm.lophine.config.modules.misc.ContainerExpansionConfig.barrelRows) { + case 6 -> net.minecraft.world.inventory.MenuType.GENERIC_9x6; + case 5 -> net.minecraft.world.inventory.MenuType.GENERIC_9x5; + case 4 -> net.minecraft.world.inventory.MenuType.GENERIC_9x4; diff --git a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/CullTask.java.patch b/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/CullTask.java.patch deleted file mode 100644 index 8737ec9..0000000 --- a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/CullTask.java.patch +++ /dev/null @@ -1,154 +0,0 @@ ---- /dev/null -+++ b/src/main/java/dev/tr7zw/entityculling/CullTask.java -@@ -1,0 +_,151 @@ -+package dev.tr7zw.entityculling; -+ -+import ca.spottedleaf.moonrise.common.util.TickThread; -+import com.logisticscraft.occlusionculling.OcclusionCullingInstance; -+import com.logisticscraft.occlusionculling.util.Vec3d; -+import dev.tr7zw.entityculling.versionless.access.Cullable; -+import me.earthme.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.decoration.ArmorStand; -+import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.phys.AABB; -+import net.minecraft.world.phys.Vec3; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.TimeUnit; -+ -+public class CullTask implements Runnable { -+ -+ private volatile boolean requestCull = false; -+ private volatile boolean scheduleNext = true; -+ private volatile boolean inited = false; -+ -+ private final OcclusionCullingInstance culling; -+ private final Player checkTarget; -+ -+ private final int hitboxLimit; -+ -+ public long lastCheckedTime = 0; -+ -+ // reused preallocated vars -+ private final Vec3d lastPos = new Vec3d(0, 0, 0); -+ private final Vec3d aabbMin = new Vec3d(0, 0, 0); -+ private final Vec3d aabbMax = new Vec3d(0, 0, 0); -+ -+ private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> { -+ final TickThread worker = new TickThread("EntityCulling") { -+ @Override -+ public void run() { -+ task.run(); -+ } -+ }; -+ -+ worker.setDaemon(true); -+ -+ return worker; -+ }); -+ -+ private final Executor worker; -+ -+ public CullTask( -+ OcclusionCullingInstance culling, -+ Player checkTarget, -+ int hitboxLimit, -+ long checkIntervalMs -+ ) { -+ this.culling = culling; -+ this.checkTarget = checkTarget; -+ this.hitboxLimit = hitboxLimit; -+ this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker); -+ } -+ -+ public void requestCullSignal() { -+ this.requestCull = true; -+ } -+ -+ public void signalStop() { -+ this.scheduleNext = false; -+ } -+ -+ public void setup() { -+ if (!this.inited) -+ this.inited = true; -+ else -+ return; -+ this.worker.execute(this); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ if (this.checkTarget.tickCount > 10) { -+ // getEyePosition can use a fixed delta as its debug only anyway -+ Vec3 cameraMC = this.checkTarget.getEyePosition(0); -+ if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) { -+ long start = System.currentTimeMillis(); -+ -+ requestCull = false; -+ -+ lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z); -+ culling.resetCache(); -+ -+ cullEntities(cameraMC, lastPos); -+ -+ lastCheckedTime = (System.currentTimeMillis() - start); -+ } -+ } -+ }finally { -+ if (this.scheduleNext) { -+ this.worker.execute(this); -+ } -+ } -+ } -+ -+ private void cullEntities(Vec3 cameraMC, Vec3d camera) { -+ for (Entity entity : this.checkTarget.level().getEntities().getAll()) { -+ if (!(entity instanceof Cullable cullable)) { -+ continue; // Not sure how this could happen outside from mixin screwing up the inject into -+ // Entity -+ } -+ -+ if (entity.getType().skipRaytracningCheck) { -+ continue; -+ } -+ -+ if (!cullable.isForcedVisible()) { -+ if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) { -+ cullable.setCulled(false); -+ continue; -+ } -+ -+ if (!entity.position().closerThan(cameraMC, RayTrackingEntityTrackerConfig.tracingDistance)) { -+ cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just -+ // render it -+ continue; -+ } -+ -+ AABB boundingBox = entity.getBoundingBox(); -+ if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit -+ || boundingBox.getZsize() > hitboxLimit) { -+ cullable.setCulled(false); // Too big to bother to cull -+ continue; -+ } -+ -+ aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ); -+ aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ); -+ -+ boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera); -+ -+ cullable.setCulled(!visible); -+ } -+ } -+ } -+ -+ private boolean isSkippableArmorstand(Entity entity) { -+ if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands) -+ return false; -+ return entity instanceof ArmorStand && entity.isInvisible(); -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java.patch b/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java.patch deleted file mode 100644 index 3bc01a0..0000000 --- a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java.patch +++ /dev/null @@ -1,45 +0,0 @@ ---- /dev/null -+++ b/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java -@@ -1,0 +_,42 @@ -+package dev.tr7zw.entityculling; -+ -+import com.logisticscraft.occlusionculling.DataProvider; -+import net.minecraft.core.BlockPos; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.chunk.ChunkAccess; -+ -+public class DefaultChunkDataProvider implements DataProvider { -+ private final Level level; -+ -+ public DefaultChunkDataProvider(Level level) { -+ this.level = level; -+ } -+ -+ @Override -+ public boolean prepareChunk(int chunkX, int chunkZ) { -+ return this.level.getChunkIfLoaded(chunkX, chunkZ) != null; -+ } -+ -+ @Override -+ public boolean isOpaqueFullCube(int x, int y, int z) { -+ BlockPos pos = new BlockPos(x, y, z); -+ -+ final ChunkAccess access = this.level.getChunkIfLoaded(pos); -+ if (access == null) { -+ return false; -+ } -+ -+ if (this.level.isOutsideBuildHeight(pos)) { -+ return Blocks.VOID_AIR.defaultBlockState().isSolidRender(); -+ } else { -+ return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截() -+ } -+ } -+ -+ @Override -+ public void cleanup() { -+ DataProvider.super.cleanup(); -+ } -+ -+} diff --git a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java.patch b/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java.patch deleted file mode 100644 index 8ffd32f..0000000 --- a/lophine-server/paper-patches/files/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- /dev/null -+++ b/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java -@@ -1,0 +_,17 @@ -+package dev.tr7zw.entityculling.versionless.access; -+ -+public interface Cullable { -+ -+ public void setTimeout(); -+ -+ public boolean isForcedVisible(); -+ -+ public void setCulled(boolean value); -+ -+ public boolean isCulled(); -+ -+ public void setOutOfCamera(boolean value); -+ -+ public boolean isOutOfCamera(); -+ -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/LophineConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/LophineConfig.java.patch deleted file mode 100644 index eb98992..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/LophineConfig.java.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/LophineConfig.java -@@ -1,0 +_,33 @@ -+package me.earthme.lophine.config; -+ -+import me.earthme.luminol.config.LuminolConfig; -+ -+import java.io.File; -+import java.io.IOException; -+import java.util.HashMap; -+import java.util.Map; -+ -+public class LophineConfig { -+ public static final Map configfiles = new HashMap<>(); -+ private static final File luminolConfigFolder = new File("luminol_config"); -+ private static final File lophineConfigFolder = new File("lophine_config"); -+ -+ public static void initConfigs() throws IOException { -+ configfiles.put("luminol", new LuminolConfig(luminolConfigFolder, "luminol", "me.earthme.luminol.config.modules")); -+ configfiles.put("lophine", new LuminolConfig(lophineConfigFolder, "lophine", "me.earthme.lophine.config.modules")); -+ preLoad(); -+ } -+ -+ public static void preLoad() throws IOException { -+ for (LuminolConfig config : configfiles.values()) { -+ config.preLoadConfig(); -+ } -+ } -+ -+ public static void loadConfigFiles() { -+ for (LuminolConfig config : configfiles.values()) { -+ config.finalizeLoadConfig(); -+ config.setupLatch(); -+ } -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java.patch deleted file mode 100644 index a444920..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/CommandConfig.java -@@ -1,0 +_,27 @@ -+package me.earthme.lophine.config.modules.experiment; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class CommandConfig implements IConfigModule { -+ @ConfigInfo(baseName = "command_block_enabled", comments = -+ """ -+ Allow to use command block""") -+ public static boolean block = false; -+ -+ @ConfigInfo(baseName = "tick_command_enabled", comments = -+ """ -+ Allow to use tick command""") -+ public static boolean tick = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.EXPERIMENT; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "command"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java.patch deleted file mode 100644 index 281e7db..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java -@@ -1,0 +_,22 @@ -+package me.earthme.lophine.config.modules.experiment; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class EntityDamageSourceTraceConfig implements IConfigModule { -+ @ConfigInfo(baseName = "enabled", comments = -+ """ -+ Allow trace damage source cross different Region Scheduler.""") -+ public static boolean enabled = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.EXPERIMENT; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "entity_damage_source_trace"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java.patch deleted file mode 100644 index fd49f47..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java -@@ -1,0 +_,28 @@ -+package me.earthme.lophine.config.modules.experiment; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class RayTrackingEntityTrackerConfig implements IConfigModule { -+ @ConfigInfo(baseName = "enabled") -+ public static boolean enabled = false; -+ @ConfigInfo(baseName = "skip_marker_armor_stands") -+ public static boolean skipMarkerArmorStands = true; -+ @ConfigInfo(baseName = "check_interval_ms") -+ public static int checkIntervalMs = 10; -+ @ConfigInfo(baseName = "tracing_distance") -+ public static int tracingDistance = 48; -+ @ConfigInfo(baseName = "hitbox_limit") -+ public static int hitboxLimit = 50; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.EXPERIMENT; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "ray_tracking_entity_tracker"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java.patch deleted file mode 100644 index fa9f531..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/misc/ContainerExpansionConfig.java -@@ -1,0 +_,37 @@ -+package me.earthme.lophine.config.modules.misc; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class ContainerExpansionConfig implements IConfigModule { -+ @ConfigInfo(baseName = "barrel_rows", comments = -+ """ -+ range: 1~6""") -+ public static int barrelRows = 3; -+ -+ @ConfigInfo(baseName = "enderchest_rows", comments = -+ """ -+ range: 1~6""") -+ public static int enderchestRows = 3; -+ -+ @ConfigInfo(baseName = "shulker_stackable_count", comments = -+ """ -+ range: 1~64""") -+ public static int shulkerCount = 1; -+ -+ @ConfigInfo(baseName = "better_shulker_box", comments = -+ """ -+ Enable sneak + use to open shulker box.""") -+ public static boolean betterShulker = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.MISC; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "container_expansion"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java.patch deleted file mode 100644 index 1da3665..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java -@@ -1,0 +_,23 @@ -+package me.earthme.lophine.config.modules.misc; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class DisableEndCrystalCheckConfig implements IConfigModule { -+ @ConfigInfo(baseName = "disable_end_crystal_check", comments = -+ """ -+ Disable paper's End Crystal position check. -+ It reverts to vanilla respawn dragon logic.""") -+ public static boolean disableCheck = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.MISC; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "end_crystal"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java.patch deleted file mode 100644 index 82c8d62..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/misc/OldFeatureConfig.java -@@ -1,0 +_,26 @@ -+package me.earthme.lophine.config.modules.misc; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class OldFeatureConfig implements IConfigModule { -+ @ConfigInfo(baseName = "old_nether_portal_collision") -+ public static boolean oldNetherPortalCollision = false; -+ -+ @ConfigInfo(baseName = "spawn_invulnerable_time") -+ public static boolean spawnInvulnerableTime = false; -+ -+ @ConfigInfo(baseName = "old_zombie_reinforcement") -+ public static boolean oldZombieReinforcement = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.MISC; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "old-feature"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java.patch deleted file mode 100644 index adf7b02..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/misc/RaidChangesConfig.java -@@ -1,0 +_,54 @@ -+package me.earthme.lophine.config.modules.misc; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class RaidChangesConfig implements IConfigModule { -+ @ConfigInfo(baseName = "allow_skip_cooldown", comments = -+ """ -+ Allow players with bad omen to skip a -+ 30-second cooldown and trigger attacks directly""") -+ public static boolean trigger = false; -+ -+ @ConfigInfo(baseName = "give_bad_omen_when_kill_raid_captain", comments = -+ """ -+ Enable players to obtain a bad omen -+ effect when killing the raid captain""") -+ public static boolean effect = false; -+ -+ @ConfigInfo(baseName = "bad_omen_infinite", comments = -+ """ -+ Enable bad omen effect infinite time -+ --- this config is not old version's function""") -+ public static boolean infinite = false; -+ -+ @ConfigInfo(baseName = "skip_height_check", comments = -+ """ -+ Disable y <= 96 check. -+ If you enabled use_old_position_find, this config -+ will useless and always behavior of enabled""") -+ public static boolean heightCheck = false; -+ -+ @ConfigInfo(baseName = "skip_self_raid_check", comments = -+ """ -+ Disable raid self check -+ --- this config is not old version's function""") -+ public static boolean selfCheck = false; -+ -+ @ConfigInfo(baseName = "use_old_position_find", comments = -+ """ -+ Revert Old raid's find spawn position logic -+ --- This revert MC-274911""") -+ public static boolean posRevert = false; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.MISC; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "revert_raid_changes"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java.patch deleted file mode 100644 index b2604f9..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/optimizations/LanguageConfig.java -@@ -1,0 +_,22 @@ -+package me.earthme.lophine.config.modules.optimizations; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+ -+public class LanguageConfig implements IConfigModule { -+ @ConfigInfo(baseName = "lang", comments = """ -+ Please use the key from https://minecraft.wiki/w/Language -+ Sample of format: en_us zh_cn zh_hk zh_tw""") -+ public static String lang = "en_us"; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.OPTIMIZATIONS; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "language"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java.patch deleted file mode 100644 index 1c156ac..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/config/modules/removed/RemovedConfig.java -@@ -1,0 +_,24 @@ -+package me.earthme.lophine.config.modules.removed; -+ -+import me.earthme.luminol.config.EnumConfigCategory; -+import me.earthme.luminol.config.IConfigModule; -+import me.earthme.luminol.config.flags.ConfigInfo; -+import me.earthme.luminol.config.flags.TransformedConfig; -+ -+public class RemovedConfig implements IConfigModule { -+ @TransformedConfig(name = "example", category = {"removed", "example"}, transform = false) -+ @ConfigInfo(baseName = "removed", comments = -+ """ -+ RemovedConfig redirect to here, no any function.""") -+ public static boolean enabled = true; -+ -+ @Override -+ public EnumConfigCategory getCategory() { -+ return EnumConfigCategory.REMOVED; -+ } -+ -+ @Override -+ public String getBaseName() { -+ return "removed_config"; -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java.patch deleted file mode 100644 index 6dd89fb..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java.patch +++ /dev/null @@ -1,254 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/utils/ServerI18nUtil.java -@@ -1,0 +_,251 @@ -+package me.earthme.lophine.utils; -+ -+import com.google.gson.JsonElement; -+import com.google.gson.JsonObject; -+import com.google.gson.JsonParser; -+import com.google.gson.JsonSyntaxException; -+import me.earthme.lophine.config.modules.optimizations.LanguageConfig; -+import net.minecraft.locale.DeprecatedTranslationsInfo; -+import net.minecraft.locale.Language; -+import net.minecraft.network.chat.FormattedText; -+import net.minecraft.network.chat.Style; -+import net.minecraft.util.FormattedCharSequence; -+import net.minecraft.util.StringDecomposer; -+import org.apache.commons.io.FileUtils; -+import org.jetbrains.annotations.NotNull; -+ -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.UnsupportedEncodingException; -+import java.net.URI; -+import java.net.http.HttpClient; -+import java.net.http.HttpRequest; -+import java.net.http.HttpResponse; -+import java.nio.file.*; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Objects; -+import java.util.Optional; -+import java.util.concurrent.CompletableFuture; -+import java.util.function.BiConsumer; -+import java.util.logging.Logger; -+ -+/* -+* authored by: Helvetica Volubi -+* modified by: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> -+* Some of diff form Leaves -+*/ -+public class ServerI18nUtil { -+ -+ private static final Logger logger = Logger.getLogger("LangLoader"); -+ private static final String VERSION = "1.21.5"; -+ private static final String BASE_PATH = "cache/lophine/" + VERSION + "/"; -+ private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json"; -+ private static final String resourceBaseUrl = "https://resources.download.minecraft.net/"; -+ -+ private static String langPath; -+ private static String assetsPath; -+ private static String versionPath; -+ private static String manifestPath; -+ private static String langJsonPath; -+ -+ public static void init() { -+ if (Objects.equals(LanguageConfig.lang, "en_us")) { -+ return; -+ } -+ langPath = BASE_PATH + "lang/" + LanguageConfig.lang + ".json"; -+ assetsPath = BASE_PATH + "assets.json"; -+ versionPath = BASE_PATH + VERSION + ".json"; -+ manifestPath = BASE_PATH + "manifest.json"; -+ langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json"; -+ logger.info("Starting load language: " + LanguageConfig.lang); -+ CompletableFuture.runAsync(() -> loadI18n(LanguageConfig.lang, 2)); -+ } -+ -+ private static void loadI18n(String lang, int retryTime) { -+ try { -+ if (!Files.exists(Path.of(langPath))) { -+ downloadLang(true); -+ } -+ Language.inject(createLangInstance()); -+ logger.info("Successfully loaded language: " + lang); -+ } catch (Exception e) { -+ logger.warning("Failed to load language file for " + lang + "\n" + e); -+ if (retryTime > 0) { -+ cleanCache(); -+ loadI18n(lang, retryTime - 1); -+ } else { -+ logger.severe("Failed to load for many times, use default lang \"en_us\" instead"); -+ cleanCache(); -+ } -+ } -+ } -+ -+ private static void downloadLang(boolean fetchFromAssets) throws Exception { -+ JsonObject json; -+ if (!Files.exists(Path.of(assetsPath)) || (json = loadJson(assetsPath)) == null) { -+ if (fetchFromAssets) { -+ downloadAssets(true); -+ downloadLang(false); -+ } -+ return; -+ } -+ -+ JsonObject langEntry = json.getAsJsonObject("objects").getAsJsonObject(langJsonPath); -+ -+ String hash = langEntry.get("hash").getAsString(); -+ if (hash == null || hash.length() < 2) { -+ throw new IllegalArgumentException("Invalid hash value"); -+ } -+ -+ String langUrl = resourceBaseUrl + hash.substring(0, 2) + "/" + hash; -+ fetchAndSave(langUrl, langPath); -+ } -+ -+ private static void downloadAssets(boolean fetchFromVersion) throws Exception { -+ JsonObject json; -+ if (!Files.exists(Path.of(versionPath)) || (json = loadJson(versionPath)) == null) { -+ if (fetchFromVersion) { -+ downloadVersion(true); -+ downloadAssets(false); -+ } -+ return; -+ } -+ -+ JsonObject assetIndex = json.getAsJsonObject("assetIndex"); -+ String assetUrl = assetIndex.get("url").getAsString(); -+ fetchAndSave(assetUrl, assetsPath); -+ } -+ -+ private static void downloadVersion(boolean fetchFromManifest) throws Exception { -+ JsonObject json; -+ if (!Files.exists(Path.of(manifestPath)) || (json = loadJson(manifestPath)) == null) { -+ if (fetchFromManifest) { -+ fetchAndSave(manifestUrl, manifestPath); -+ downloadVersion(false); -+ } -+ return; -+ } -+ -+ String versionUrl = null; -+ for (JsonElement element : json.getAsJsonArray("versions")) { -+ String id = element.getAsJsonObject().get("id").getAsString(); -+ String url = element.getAsJsonObject().get("url").getAsString(); -+ if (VERSION.equals(id)) { -+ versionUrl = url; -+ break; -+ } -+ } -+ -+ if (versionUrl == null) { -+ throw new RuntimeException("Could not find version URL"); -+ } -+ -+ fetchAndSave(versionUrl, versionPath); -+ } -+ -+ private static String createHttpResponse(String path) throws IOException, InterruptedException { -+ try { -+ HttpResponse response; -+ try (HttpClient httpClient = HttpClient.newHttpClient()) { -+ -+ HttpRequest request = HttpRequest.newBuilder() -+ .uri(URI.create(path)) -+ .build(); -+ -+ response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); -+ } -+ -+ int responseCode = response.statusCode(); -+ if (responseCode != 200) { -+ logger.info("Unexpected response code: " + responseCode); -+ logger.info("Response body: " + response.body()); -+ throw new UnsupportedEncodingException("Unexpected response code"); -+ } else { -+ return response.body(); -+ } -+ } catch (Exception e) { -+ logger.warning("Error in getting info: " + e.getMessage()); -+ throw e; -+ } -+ } -+ -+ private static byte[] fetch(String urlString) throws IOException, InterruptedException { -+ String ret = createHttpResponse(urlString); -+ return ret.getBytes(); -+ } -+ -+ private static void fetchAndSave(String url, String savePath) throws IOException, InterruptedException { -+ byte[] data = fetch(url); -+ Path outputPath = Path.of(savePath); -+ Files.createDirectories(outputPath.getParent()); -+ Files.write(outputPath, data, StandardOpenOption.CREATE, StandardOpenOption.WRITE); -+ } -+ -+ private static void cleanCache() { -+ try { -+ FileUtils.deleteDirectory(Path.of(BASE_PATH).toFile()); -+ } catch (IOException e) { -+ logger.severe("Cache cleanup failed: " + e); -+ } -+ } -+ -+ private static JsonObject loadJson(String path) { -+ try { -+ byte[] data = Files.readAllBytes(Paths.get(path)); -+ return JsonParser.parseString(new String(data)).getAsJsonObject(); -+ } catch (JsonSyntaxException e) { -+ logger.warning("Corrupt json file: " + e); -+ throw e; -+ } catch (Exception e) { -+ logger.warning("Failed to load local JSON: " + e); -+ return null; -+ } -+ } -+ -+ private static Language createLangInstance() throws IOException { -+ DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource(); -+ Map map = new HashMap<>(); -+ parseTranslations(map::put); -+ deprecatedTranslationsInfo.applyToMap(map); -+ final Map map1 = Map.copyOf(map); -+ return new Language() { -+ @Override -+ public @NotNull String getOrDefault(@NotNull String key, @NotNull String defaultValue) { -+ return map1.getOrDefault(key, defaultValue); -+ } -+ -+ @Override -+ public boolean has(@NotNull String id) { -+ return map1.containsKey(id); -+ } -+ -+ @Override -+ public boolean isDefaultRightToLeft() { -+ return false; -+ } -+ -+ @Override -+ public @NotNull FormattedCharSequence getVisualOrder(@NotNull FormattedText text) { -+ return sink -> text.visit( -+ (style, content) -> StringDecomposer.iterateFormatted(content, style, sink) ? Optional.empty() : FormattedText.STOP_ITERATION, -+ Style.EMPTY -+ ) -+ .isPresent(); -+ } -+ }; -+ } -+ -+ private static void parseTranslations(BiConsumer output) throws IOException { -+ Path filePath = Path.of(langPath); -+ try (InputStream fileStream = Files.newInputStream(filePath)) { -+ Language.loadFromJson(fileStream, output); -+ } catch (NoSuchFileException noSuchFileException) { -+ logger.warning("Couldn't find language file: " + langPath); -+ throw noSuchFileException; -+ } catch (Exception e) { -+ logger.warning("Failed to load language from filesystem " + filePath + "\n" + e); -+ throw e; -+ } -+ } -+} diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java.patch deleted file mode 100644 index 93fb3e1..0000000 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java.patch +++ /dev/null @@ -1,184 +0,0 @@ ---- /dev/null -+++ b/src/main/java/me/earthme/lophine/utils/ShulkerBoxesUtil.java -@@ -1,0 +_,181 @@ -+package me.earthme.lophine.utils; -+ -+import me.earthme.lophine.config.modules.misc.ContainerExpansionConfig; -+import net.minecraft.core.NonNullList; -+import net.minecraft.core.component.DataComponents; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.stats.Stats; -+import net.minecraft.world.InteractionHand; -+import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.item.BlockItem; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.component.CustomData; -+import net.minecraft.world.item.component.ItemContainerContents; -+import net.minecraft.world.level.block.ShulkerBoxBlock; -+import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.HashMap; -+import java.util.Objects; -+import java.util.Optional; -+ -+public class ShulkerBoxesUtil { -+ // Better ShulkerBoxes used -+ public static HashMap shulkerMap = new HashMap<>(); -+ public static HashMap playerMap = new HashMap<>(); -+ -+ // Stackable ShulkerBoxes part -+ public static boolean shouldCheck() { -+ return ContainerExpansionConfig.shulkerCount > 1 && ContainerExpansionConfig.shulkerCount <= 64; -+ } -+ -+ public static boolean checkShulkerBox(ItemStack itemStack) { -+ return shouldCheck() && checkIsShulkerBox(itemStack); -+ } -+ -+ public static boolean checkIsShulkerBox(ItemStack itemStack) { -+ return itemStack.getItem() instanceof BlockItem b && b.getBlock() instanceof ShulkerBoxBlock; -+ } -+ -+ public static int getItemMaxCount(ItemStack itemStack) { -+ if (checkShulkerBox(itemStack)) { -+ return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64); -+ } -+ return itemStack.getMaxStackSize(); -+ } -+ -+ public static int getShulkerBoxesMaxCountUnsafe() { -+ return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64); -+ } -+ -+ public static boolean emptyShulkerBoxCheck(@NotNull ItemStack stack) { -+ return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty(); -+ } -+ -+ public static boolean isStackable(ItemStack itemStack) { -+ return getItemMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged()); -+ } -+ -+ public static int getItemStackMaxCountReal(ItemStack stack) { -+ CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag(); -+ return nbt.getInt("Lophine.RealStackSize").orElse(stack.getMaxStackSize()); -+ } -+ -+ public static ItemStack encodeMaxStackSize(ItemStack itemStack) { -+ int realMaxStackSize = getItemStackMaxCountReal(itemStack); -+ int modifiedMaxStackSize = getItemMaxCount(itemStack); -+ if (itemStack.getMaxStackSize() != modifiedMaxStackSize) { -+ itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize); -+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); -+ nbt.putInt("Lophine.RealStackSize", realMaxStackSize); -+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); -+ } -+ return itemStack; -+ } -+ -+ public static ItemStack decodeMaxStackSize(ItemStack itemStack) { -+ int realMaxStackSize = getItemStackMaxCountReal(itemStack); -+ if (itemStack.getMaxStackSize() != realMaxStackSize) { -+ itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize); -+ CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); -+ nbt.remove("Lophine.RealStackSize"); -+ if (nbt.isEmpty()) { -+ itemStack.remove(DataComponents.CUSTOM_DATA); -+ } else { -+ itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); -+ } -+ } -+ return itemStack; -+ } -+ -+ // Better ShulkerBox part -+ public static boolean checkIfCanOpen(ItemStack itemStack) { -+ return checkIsShulkerBox(itemStack) && itemStack.getCount() == 1; -+ } -+ -+ public static boolean checkIfValid(Player player) { -+ return shulkerMap.get(player) != null; -+ } -+ -+ public static void openShulkerBox(Player player, ItemStack item, InteractionHand hand) { -+ ItemStack itemInHand = item.copy(); -+ ShulkerBoxBlockEntity shulkerBoxEntity = new ShulkerBoxBlockEntity( -+ player.blockPosition(), -+ ((BlockItem) itemInHand.getItem()).getBlock().defaultBlockState() -+ ); -+ ItemContainerContents container = itemInHand.getOrDefault( -+ DataComponents.CONTAINER, -+ ItemContainerContents.EMPTY -+ ); -+ -+ NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); -+ for (int i = 0; i < container.items.size(); i++) { -+ items.set(i, container.items.get(i)); -+ } -+ -+ shulkerBoxEntity.setItems(items); -+ -+ shulkerBoxEntity.haveRealBlock = false; -+ shulkerBoxEntity.shulkerHand = hand; -+ shulkerBoxEntity.finalItem = itemInHand; -+ shulkerBoxEntity.setLevel(player.level()); -+ -+ shulkerMap.put(player, shulkerBoxEntity); -+ playerMap.put(shulkerBoxEntity, player); -+ -+ if (player.openMenu(shulkerBoxEntity).isPresent()) { -+ player.awardStat(Stats.OPEN_SHULKER_BOX); -+ } -+ } -+ -+ public static void shulkerBoxEntityCallBack(ShulkerBoxBlockEntity shulkerBoxEntity) { -+ Player player = playerMap.get(shulkerBoxEntity); -+ if (player != null) { -+ InteractionHand hand = shulkerBoxEntity.shulkerHand; -+ ItemStack currentItem = player.getItemInHand(hand); -+ ItemStack copy = currentItem.copy(); -+ -+ copy.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(shulkerBoxEntity.getItems())); -+ -+ player.setItemInHand(hand, copy); -+ -+ shulkerBoxEntity.finalItem = copy; -+ } -+ } -+ -+ public static void inventoryCallBack(boolean isMainHand, Player player) { -+ ShulkerBoxBlockEntity entity = shulkerMap.get(player); -+ if (entity != null && isMainHand == Objects.equals(entity.shulkerHand, InteractionHand.MAIN_HAND)) { -+ closeScreen(entity, player); -+ } -+ } -+ -+ public static void closeScreen(ShulkerBoxBlockEntity entity, Player player) { -+ if (player instanceof ServerPlayer serverPlayer) { -+ ItemStack stack1 = entity.finalItem; -+ ItemStack stack2 = player.containerMenu.getCarried(); -+ ItemStack stack = stack2.isEmpty() ? stack1 : stack2; -+ if (!stack.isEmpty()) { -+ if (!player.isAlive() || serverPlayer.hasDisconnected()) { -+ player.drop(stack, false); -+ } else { -+ player.getInventory().placeItemBackInInventory(stack); -+ } -+ } -+ } -+ player.closeContainer(); -+ } -+ -+ public static void clearMap(Player p) { -+ ShulkerBoxBlockEntity e = shulkerMap.get(p); -+ if (e != null) playerMap.remove(e); -+ shulkerMap.remove(p); -+ } -+ -+ public static void clearMap(ShulkerBoxBlockEntity e) { -+ Player p = playerMap.get(e); -+ if (p != null) shulkerMap.remove(p); -+ playerMap.remove(e); -+ } -+} diff --git a/lophine-server/src/main/java/dev/tr7zw/entityculling/CullTask.java b/lophine-server/src/main/java/dev/tr7zw/entityculling/CullTask.java new file mode 100644 index 0000000..a1bafe4 --- /dev/null +++ b/lophine-server/src/main/java/dev/tr7zw/entityculling/CullTask.java @@ -0,0 +1,151 @@ +package dev.tr7zw.entityculling; + +import ca.spottedleaf.moonrise.common.util.TickThread; +import com.logisticscraft.occlusionculling.OcclusionCullingInstance; +import com.logisticscraft.occlusionculling.util.Vec3d; +import dev.tr7zw.entityculling.versionless.access.Cullable; +import fun.bm.lophine.config.modules.experiment.RayTrackingEntityTrackerConfig; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class CullTask implements Runnable { + + private volatile boolean requestCull = false; + private volatile boolean scheduleNext = true; + private volatile boolean inited = false; + + private final OcclusionCullingInstance culling; + private final Player checkTarget; + + private final int hitboxLimit; + + public long lastCheckedTime = 0; + + // reused preallocated vars + private final Vec3d lastPos = new Vec3d(0, 0, 0); + private final Vec3d aabbMin = new Vec3d(0, 0, 0); + private final Vec3d aabbMax = new Vec3d(0, 0, 0); + + private static final Executor backgroundWorker = Executors.newCachedThreadPool(task -> { + final TickThread worker = new TickThread("EntityCulling") { + @Override + public void run() { + task.run(); + } + }; + + worker.setDaemon(true); + + return worker; + }); + + private final Executor worker; + + public CullTask( + OcclusionCullingInstance culling, + Player checkTarget, + int hitboxLimit, + long checkIntervalMs + ) { + this.culling = culling; + this.checkTarget = checkTarget; + this.hitboxLimit = hitboxLimit; + this.worker = CompletableFuture.delayedExecutor(checkIntervalMs, TimeUnit.MILLISECONDS, backgroundWorker); + } + + public void requestCullSignal() { + this.requestCull = true; + } + + public void signalStop() { + this.scheduleNext = false; + } + + public void setup() { + if (!this.inited) + this.inited = true; + else + return; + this.worker.execute(this); + } + + @Override + public void run() { + try { + if (this.checkTarget.tickCount > 10) { + // getEyePosition can use a fixed delta as its debug only anyway + Vec3 cameraMC = this.checkTarget.getEyePosition(0); + if (requestCull || !(cameraMC.x == lastPos.x && cameraMC.y == lastPos.y && cameraMC.z == lastPos.z)) { + long start = System.currentTimeMillis(); + + requestCull = false; + + lastPos.set(cameraMC.x, cameraMC.y, cameraMC.z); + culling.resetCache(); + + cullEntities(cameraMC, lastPos); + + lastCheckedTime = (System.currentTimeMillis() - start); + } + } + }finally { + if (this.scheduleNext) { + this.worker.execute(this); + } + } + } + + private void cullEntities(Vec3 cameraMC, Vec3d camera) { + for (Entity entity : this.checkTarget.level().getEntities().getAll()) { + if (!(entity instanceof Cullable cullable)) { + continue; // Not sure how this could happen outside from mixin screwing up the inject into + // Entity + } + + if (entity.getType().skipRaytracningCheck) { + continue; + } + + if (!cullable.isForcedVisible()) { + if (entity.isCurrentlyGlowing() || isSkippableArmorstand(entity)) { + cullable.setCulled(false); + continue; + } + + if (!entity.position().closerThan(cameraMC, RayTrackingEntityTrackerConfig.tracingDistance)) { + cullable.setCulled(false); // If your entity view distance is larger than tracingDistance just + // render it + continue; + } + + AABB boundingBox = entity.getBoundingBox(); + if (boundingBox.getXsize() > hitboxLimit || boundingBox.getYsize() > hitboxLimit + || boundingBox.getZsize() > hitboxLimit) { + cullable.setCulled(false); // Too big to bother to cull + continue; + } + + aabbMin.set(boundingBox.minX, boundingBox.minY, boundingBox.minZ); + aabbMax.set(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ); + + boolean visible = culling.isAABBVisible(aabbMin, aabbMax, camera); + + cullable.setCulled(!visible); + } + } + } + + private boolean isSkippableArmorstand(Entity entity) { + if (!RayTrackingEntityTrackerConfig.skipMarkerArmorStands) + return false; + return entity instanceof ArmorStand && entity.isInvisible(); + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java b/lophine-server/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java new file mode 100644 index 0000000..489ed8b --- /dev/null +++ b/lophine-server/src/main/java/dev/tr7zw/entityculling/DefaultChunkDataProvider.java @@ -0,0 +1,42 @@ +package dev.tr7zw.entityculling; + +import com.logisticscraft.occlusionculling.DataProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.chunk.ChunkAccess; + +public class DefaultChunkDataProvider implements DataProvider { + private final Level level; + + public DefaultChunkDataProvider(Level level) { + this.level = level; + } + + @Override + public boolean prepareChunk(int chunkX, int chunkZ) { + return this.level.getChunkIfLoaded(chunkX, chunkZ) != null; + } + + @Override + public boolean isOpaqueFullCube(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + + final ChunkAccess access = this.level.getChunkIfLoaded(pos); + if (access == null) { + return false; + } + + if (this.level.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState().isSolidRender(); + } else { + return access.getBlockState(pos).isSolidRender();// 好孩子不要学坏叔叔这样绕过异步拦截() + } + } + + @Override + public void cleanup() { + DataProvider.super.cleanup(); + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java b/lophine-server/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java new file mode 100644 index 0000000..d0359ba --- /dev/null +++ b/lophine-server/src/main/java/dev/tr7zw/entityculling/versionless/access/Cullable.java @@ -0,0 +1,17 @@ +package dev.tr7zw.entityculling.versionless.access; + +public interface Cullable { + + public void setTimeout(); + + public boolean isForcedVisible(); + + public void setCulled(boolean value); + + public boolean isCulled(); + + public void setOutOfCamera(boolean value); + + public boolean isOutOfCamera(); + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/LophineConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/LophineConfig.java new file mode 100644 index 0000000..7023955 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/LophineConfig.java @@ -0,0 +1,33 @@ +package fun.bm.lophine.config; + +import me.earthme.luminol.config.LuminolConfig; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class LophineConfig { + public static final Map configfiles = new HashMap<>(); + private static final File luminolConfigFolder = new File("luminol_config"); + private static final File lophineConfigFolder = new File("lophine_config"); + + public static void initConfigs() throws IOException { + configfiles.put("luminol", new LuminolConfig(luminolConfigFolder, "luminol", "me.earthme.luminol.config.modules")); + configfiles.put("lophine", new LuminolConfig(lophineConfigFolder, "lophine", "fun.bm.lophine.config.modules")); + preLoad(); + } + + public static void preLoad() throws IOException { + for (LuminolConfig config : configfiles.values()) { + config.preLoadConfig(); + } + } + + public static void loadConfigFiles() { + for (LuminolConfig config : configfiles.values()) { + config.finalizeLoadConfig(); + config.setupLatch(); + } + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java new file mode 100644 index 0000000..084286e --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java @@ -0,0 +1,27 @@ +package fun.bm.lophine.config.modules.experiment; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class CommandConfig implements IConfigModule { + @ConfigInfo(baseName = "command_block_enabled", comments = + """ + Allow to use command block""") + public static boolean block = false; + + @ConfigInfo(baseName = "tick_command_enabled", comments = + """ + Allow to use tick command""") + public static boolean tick = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.EXPERIMENT; + } + + @Override + public String getBaseName() { + return "command"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java new file mode 100644 index 0000000..b8f810c --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java @@ -0,0 +1,22 @@ +package fun.bm.lophine.config.modules.experiment; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class EntityDamageSourceTraceConfig implements IConfigModule { + @ConfigInfo(baseName = "enabled", comments = + """ + Allow trace damage source cross different Region Scheduler.""") + public static boolean enabled = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.EXPERIMENT; + } + + @Override + public String getBaseName() { + return "entity_damage_source_trace"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java new file mode 100644 index 0000000..356458f --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java @@ -0,0 +1,28 @@ +package fun.bm.lophine.config.modules.experiment; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class RayTrackingEntityTrackerConfig implements IConfigModule { + @ConfigInfo(baseName = "enabled") + public static boolean enabled = false; + @ConfigInfo(baseName = "skip_marker_armor_stands") + public static boolean skipMarkerArmorStands = true; + @ConfigInfo(baseName = "check_interval_ms") + public static int checkIntervalMs = 10; + @ConfigInfo(baseName = "tracing_distance") + public static int tracingDistance = 48; + @ConfigInfo(baseName = "hitbox_limit") + public static int hitboxLimit = 50; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.EXPERIMENT; + } + + @Override + public String getBaseName() { + return "ray_tracking_entity_tracker"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java new file mode 100644 index 0000000..f59caf5 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java @@ -0,0 +1,37 @@ +package fun.bm.lophine.config.modules.misc; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class ContainerExpansionConfig implements IConfigModule { + @ConfigInfo(baseName = "barrel_rows", comments = + """ + range: 1~6""") + public static int barrelRows = 3; + + @ConfigInfo(baseName = "enderchest_rows", comments = + """ + range: 1~6""") + public static int enderchestRows = 3; + + @ConfigInfo(baseName = "shulker_stackable_count", comments = + """ + range: 1~64""") + public static int shulkerCount = 1; + + @ConfigInfo(baseName = "better_shulker_box", comments = + """ + Enable sneak + use to open shulker box.""") + public static boolean betterShulker = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.MISC; + } + + @Override + public String getBaseName() { + return "container_expansion"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java new file mode 100644 index 0000000..7b71ab7 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableEndCrystalCheckConfig.java @@ -0,0 +1,23 @@ +package fun.bm.lophine.config.modules.misc; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class DisableEndCrystalCheckConfig implements IConfigModule { + @ConfigInfo(baseName = "disable_end_crystal_check", comments = + """ + Disable paper's End Crystal position check. + It reverts to vanilla respawn dragon logic.""") + public static boolean disableCheck = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.MISC; + } + + @Override + public String getBaseName() { + return "end_crystal"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java new file mode 100644 index 0000000..89d126a --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java @@ -0,0 +1,29 @@ +package fun.bm.lophine.config.modules.misc; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class OldFeatureConfig implements IConfigModule { + @ConfigInfo(baseName = "old_nether_portal_collision") + public static boolean oldNetherPortalCollision = false; + + @ConfigInfo(baseName = "spawn_invulnerable_time") + public static boolean spawnInvulnerableTime = false; + + @ConfigInfo(baseName = "old_zombie_reinforcement") + public static boolean oldZombieReinforcement = false; + + @ConfigInfo(baseName = "old_replaceable_by_mushrooms") + public static boolean oldReplaceableByMushrooms = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.MISC; + } + + @Override + public String getBaseName() { + return "old-feature"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RaidChangesConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RaidChangesConfig.java new file mode 100644 index 0000000..e793d37 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RaidChangesConfig.java @@ -0,0 +1,54 @@ +package fun.bm.lophine.config.modules.misc; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class RaidChangesConfig implements IConfigModule { + @ConfigInfo(baseName = "allow_skip_cooldown", comments = + """ + Allow players with bad omen to skip a + 30-second cooldown and trigger attacks directly""") + public static boolean trigger = false; + + @ConfigInfo(baseName = "give_bad_omen_when_kill_raid_captain", comments = + """ + Enable players to obtain a bad omen + effect when killing the raid captain""") + public static boolean effect = false; + + @ConfigInfo(baseName = "bad_omen_infinite", comments = + """ + Enable bad omen effect infinite time + --- this config is not old version's function""") + public static boolean infinite = false; + + @ConfigInfo(baseName = "skip_height_check", comments = + """ + Disable y <= 96 check. + If you enabled use_old_position_find, this config + will useless and always behavior of enabled""") + public static boolean heightCheck = false; + + @ConfigInfo(baseName = "skip_self_raid_check", comments = + """ + Disable raid self check + --- this config is not old version's function""") + public static boolean selfCheck = false; + + @ConfigInfo(baseName = "use_old_position_find", comments = + """ + Revert Old raid's find spawn position logic + --- This revert MC-274911""") + public static boolean posRevert = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.MISC; + } + + @Override + public String getBaseName() { + return "revert_raid_changes"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java new file mode 100644 index 0000000..a8c0ad5 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java @@ -0,0 +1,22 @@ +package fun.bm.lophine.config.modules.optimizations; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; + +public class LanguageConfig implements IConfigModule { + @ConfigInfo(baseName = "lang", comments = """ + Please use the key from https://minecraft.wiki/w/Language + Sample of format: en_us zh_cn zh_hk zh_tw""") + public static String lang = "en_us"; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.OPTIMIZATIONS; + } + + @Override + public String getBaseName() { + return "language"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java new file mode 100644 index 0000000..7f6b012 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java @@ -0,0 +1,24 @@ +package fun.bm.lophine.config.modules.removed; + +import me.earthme.luminol.config.EnumConfigCategory; +import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigInfo; +import me.earthme.luminol.config.flags.TransformedConfig; + +public class RemovedConfig implements IConfigModule { + @TransformedConfig(name = "example", category = {"removed", "example"}, transform = false) + @ConfigInfo(baseName = "removed", comments = + """ + RemovedConfig redirect to here, no any function.""") + public static boolean enabled = true; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.REMOVED; + } + + @Override + public String getBaseName() { + return "removed_config"; + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/utils/ServerI18nUtil.java b/lophine-server/src/main/java/fun/bm/lophine/utils/ServerI18nUtil.java new file mode 100644 index 0000000..66524e0 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/utils/ServerI18nUtil.java @@ -0,0 +1,251 @@ +package fun.bm.lophine.utils; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import fun.bm.lophine.config.modules.optimizations.LanguageConfig; +import net.minecraft.locale.DeprecatedTranslationsInfo; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.Style; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.StringDecomposer; +import org.apache.commons.io.FileUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.logging.Logger; + +/* +* authored by: Helvetica Volubi +* modified by: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +* Some of diff form Leaves +*/ +public class ServerI18nUtil { + + private static final Logger logger = Logger.getLogger("LangLoader"); + private static final String VERSION = "1.21.5"; + private static final String BASE_PATH = "cache/lophine/" + VERSION + "/"; + private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json"; + private static final String resourceBaseUrl = "https://resources.download.minecraft.net/"; + + private static String langPath; + private static String assetsPath; + private static String versionPath; + private static String manifestPath; + private static String langJsonPath; + + public static void init() { + if (Objects.equals(LanguageConfig.lang, "en_us")) { + return; + } + langPath = BASE_PATH + "lang/" + LanguageConfig.lang + ".json"; + assetsPath = BASE_PATH + "assets.json"; + versionPath = BASE_PATH + VERSION + ".json"; + manifestPath = BASE_PATH + "manifest.json"; + langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json"; + logger.info("Starting load language: " + LanguageConfig.lang); + CompletableFuture.runAsync(() -> loadI18n(LanguageConfig.lang, 2)); + } + + private static void loadI18n(String lang, int retryTime) { + try { + if (!Files.exists(Path.of(langPath))) { + downloadLang(true); + } + Language.inject(createLangInstance()); + logger.info("Successfully loaded language: " + lang); + } catch (Exception e) { + logger.warning("Failed to load language file for " + lang + "\n" + e); + if (retryTime > 0) { + cleanCache(); + loadI18n(lang, retryTime - 1); + } else { + logger.severe("Failed to load for many times, use default lang \"en_us\" instead"); + cleanCache(); + } + } + } + + private static void downloadLang(boolean fetchFromAssets) throws Exception { + JsonObject json; + if (!Files.exists(Path.of(assetsPath)) || (json = loadJson(assetsPath)) == null) { + if (fetchFromAssets) { + downloadAssets(true); + downloadLang(false); + } + return; + } + + JsonObject langEntry = json.getAsJsonObject("objects").getAsJsonObject(langJsonPath); + + String hash = langEntry.get("hash").getAsString(); + if (hash == null || hash.length() < 2) { + throw new IllegalArgumentException("Invalid hash value"); + } + + String langUrl = resourceBaseUrl + hash.substring(0, 2) + "/" + hash; + fetchAndSave(langUrl, langPath); + } + + private static void downloadAssets(boolean fetchFromVersion) throws Exception { + JsonObject json; + if (!Files.exists(Path.of(versionPath)) || (json = loadJson(versionPath)) == null) { + if (fetchFromVersion) { + downloadVersion(true); + downloadAssets(false); + } + return; + } + + JsonObject assetIndex = json.getAsJsonObject("assetIndex"); + String assetUrl = assetIndex.get("url").getAsString(); + fetchAndSave(assetUrl, assetsPath); + } + + private static void downloadVersion(boolean fetchFromManifest) throws Exception { + JsonObject json; + if (!Files.exists(Path.of(manifestPath)) || (json = loadJson(manifestPath)) == null) { + if (fetchFromManifest) { + fetchAndSave(manifestUrl, manifestPath); + downloadVersion(false); + } + return; + } + + String versionUrl = null; + for (JsonElement element : json.getAsJsonArray("versions")) { + String id = element.getAsJsonObject().get("id").getAsString(); + String url = element.getAsJsonObject().get("url").getAsString(); + if (VERSION.equals(id)) { + versionUrl = url; + break; + } + } + + if (versionUrl == null) { + throw new RuntimeException("Could not find version URL"); + } + + fetchAndSave(versionUrl, versionPath); + } + + private static String createHttpResponse(String path) throws IOException, InterruptedException { + try { + HttpResponse response; + try (HttpClient httpClient = HttpClient.newHttpClient()) { + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(path)) + .build(); + + response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + } + + int responseCode = response.statusCode(); + if (responseCode != 200) { + logger.info("Unexpected response code: " + responseCode); + logger.info("Response body: " + response.body()); + throw new UnsupportedEncodingException("Unexpected response code"); + } else { + return response.body(); + } + } catch (Exception e) { + logger.warning("Error in getting info: " + e.getMessage()); + throw e; + } + } + + private static byte[] fetch(String urlString) throws IOException, InterruptedException { + String ret = createHttpResponse(urlString); + return ret.getBytes(); + } + + private static void fetchAndSave(String url, String savePath) throws IOException, InterruptedException { + byte[] data = fetch(url); + Path outputPath = Path.of(savePath); + Files.createDirectories(outputPath.getParent()); + Files.write(outputPath, data, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + } + + private static void cleanCache() { + try { + FileUtils.deleteDirectory(Path.of(BASE_PATH).toFile()); + } catch (IOException e) { + logger.severe("Cache cleanup failed: " + e); + } + } + + private static JsonObject loadJson(String path) { + try { + byte[] data = Files.readAllBytes(Paths.get(path)); + return JsonParser.parseString(new String(data)).getAsJsonObject(); + } catch (JsonSyntaxException e) { + logger.warning("Corrupt json file: " + e); + throw e; + } catch (Exception e) { + logger.warning("Failed to load local JSON: " + e); + return null; + } + } + + private static Language createLangInstance() throws IOException { + DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource(); + Map map = new HashMap<>(); + parseTranslations(map::put); + deprecatedTranslationsInfo.applyToMap(map); + final Map map1 = Map.copyOf(map); + return new Language() { + @Override + public @NotNull String getOrDefault(@NotNull String key, @NotNull String defaultValue) { + return map1.getOrDefault(key, defaultValue); + } + + @Override + public boolean has(@NotNull String id) { + return map1.containsKey(id); + } + + @Override + public boolean isDefaultRightToLeft() { + return false; + } + + @Override + public @NotNull FormattedCharSequence getVisualOrder(@NotNull FormattedText text) { + return sink -> text.visit( + (style, content) -> StringDecomposer.iterateFormatted(content, style, sink) ? Optional.empty() : FormattedText.STOP_ITERATION, + Style.EMPTY + ) + .isPresent(); + } + }; + } + + private static void parseTranslations(BiConsumer output) throws IOException { + Path filePath = Path.of(langPath); + try (InputStream fileStream = Files.newInputStream(filePath)) { + Language.loadFromJson(fileStream, output); + } catch (NoSuchFileException noSuchFileException) { + logger.warning("Couldn't find language file: " + langPath); + throw noSuchFileException; + } catch (Exception e) { + logger.warning("Failed to load language from filesystem " + filePath + "\n" + e); + throw e; + } + } +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/utils/ShulkerBoxesUtil.java b/lophine-server/src/main/java/fun/bm/lophine/utils/ShulkerBoxesUtil.java new file mode 100644 index 0000000..20e9524 --- /dev/null +++ b/lophine-server/src/main/java/fun/bm/lophine/utils/ShulkerBoxesUtil.java @@ -0,0 +1,181 @@ +package fun.bm.lophine.utils; + +import fun.bm.lophine.config.modules.misc.ContainerExpansionConfig; +import net.minecraft.core.NonNullList; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.ItemContainerContents; +import net.minecraft.world.level.block.ShulkerBoxBlock; +import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Objects; +import java.util.Optional; + +public class ShulkerBoxesUtil { + // Better ShulkerBoxes used + public static HashMap shulkerMap = new HashMap<>(); + public static HashMap playerMap = new HashMap<>(); + + // Stackable ShulkerBoxes part + public static boolean shouldCheck() { + return ContainerExpansionConfig.shulkerCount > 1 && ContainerExpansionConfig.shulkerCount <= 64; + } + + public static boolean checkShulkerBox(ItemStack itemStack) { + return shouldCheck() && checkIsShulkerBox(itemStack); + } + + public static boolean checkIsShulkerBox(ItemStack itemStack) { + return itemStack.getItem() instanceof BlockItem b && b.getBlock() instanceof ShulkerBoxBlock; + } + + public static int getItemMaxCount(ItemStack itemStack) { + if (checkShulkerBox(itemStack)) { + return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64); + } + return itemStack.getMaxStackSize(); + } + + public static int getShulkerBoxesMaxCountUnsafe() { + return Math.clamp(ContainerExpansionConfig.shulkerCount, 1, 64); + } + + public static boolean emptyShulkerBoxCheck(@NotNull ItemStack stack) { + return stack.getComponents().getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).stream().findAny().isEmpty(); + } + + public static boolean isStackable(ItemStack itemStack) { + return getItemMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged()); + } + + public static int getItemStackMaxCountReal(ItemStack stack) { + CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag(); + return nbt.getInt("Lophine.RealStackSize").orElse(stack.getMaxStackSize()); + } + + public static ItemStack encodeMaxStackSize(ItemStack itemStack) { + int realMaxStackSize = getItemStackMaxCountReal(itemStack); + int modifiedMaxStackSize = getItemMaxCount(itemStack); + if (itemStack.getMaxStackSize() != modifiedMaxStackSize) { + itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize); + CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + nbt.putInt("Lophine.RealStackSize", realMaxStackSize); + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); + } + return itemStack; + } + + public static ItemStack decodeMaxStackSize(ItemStack itemStack) { + int realMaxStackSize = getItemStackMaxCountReal(itemStack); + if (itemStack.getMaxStackSize() != realMaxStackSize) { + itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize); + CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + nbt.remove("Lophine.RealStackSize"); + if (nbt.isEmpty()) { + itemStack.remove(DataComponents.CUSTOM_DATA); + } else { + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); + } + } + return itemStack; + } + + // Better ShulkerBox part + public static boolean checkIfCanOpen(ItemStack itemStack) { + return checkIsShulkerBox(itemStack) && itemStack.getCount() == 1; + } + + public static boolean checkIfValid(Player player) { + return shulkerMap.get(player) != null; + } + + public static void openShulkerBox(Player player, ItemStack item, InteractionHand hand) { + ItemStack itemInHand = item.copy(); + ShulkerBoxBlockEntity shulkerBoxEntity = new ShulkerBoxBlockEntity( + player.blockPosition(), + ((BlockItem) itemInHand.getItem()).getBlock().defaultBlockState() + ); + ItemContainerContents container = itemInHand.getOrDefault( + DataComponents.CONTAINER, + ItemContainerContents.EMPTY + ); + + NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); + for (int i = 0; i < container.items.size(); i++) { + items.set(i, container.items.get(i)); + } + + shulkerBoxEntity.setItems(items); + + shulkerBoxEntity.haveRealBlock = false; + shulkerBoxEntity.shulkerHand = hand; + shulkerBoxEntity.finalItem = itemInHand; + shulkerBoxEntity.setLevel(player.level()); + + shulkerMap.put(player, shulkerBoxEntity); + playerMap.put(shulkerBoxEntity, player); + + if (player.openMenu(shulkerBoxEntity).isPresent()) { + player.awardStat(Stats.OPEN_SHULKER_BOX); + } + } + + public static void shulkerBoxEntityCallBack(ShulkerBoxBlockEntity shulkerBoxEntity) { + Player player = playerMap.get(shulkerBoxEntity); + if (player != null) { + InteractionHand hand = shulkerBoxEntity.shulkerHand; + ItemStack currentItem = player.getItemInHand(hand); + ItemStack copy = currentItem.copy(); + + copy.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(shulkerBoxEntity.getItems())); + + player.setItemInHand(hand, copy); + + shulkerBoxEntity.finalItem = copy; + } + } + + public static void inventoryCallBack(boolean isMainHand, Player player) { + ShulkerBoxBlockEntity entity = shulkerMap.get(player); + if (entity != null && isMainHand == Objects.equals(entity.shulkerHand, InteractionHand.MAIN_HAND)) { + closeScreen(entity, player); + } + } + + public static void closeScreen(ShulkerBoxBlockEntity entity, Player player) { + if (player instanceof ServerPlayer serverPlayer) { + ItemStack stack1 = entity.finalItem; + ItemStack stack2 = player.containerMenu.getCarried(); + ItemStack stack = stack2.isEmpty() ? stack1 : stack2; + if (!stack.isEmpty()) { + if (!player.isAlive() || serverPlayer.hasDisconnected()) { + player.drop(stack, false); + } else { + player.getInventory().placeItemBackInInventory(stack); + } + } + } + player.closeContainer(); + } + + public static void clearMap(Player p) { + ShulkerBoxBlockEntity e = shulkerMap.get(p); + if (e != null) playerMap.remove(e); + shulkerMap.remove(p); + } + + public static void clearMap(ShulkerBoxBlockEntity e) { + Player p = playerMap.get(e); + if (p != null) shulkerMap.remove(p); + playerMap.remove(e); + } +} \ No newline at end of file