diff --git a/README.md b/README.md index 7dc98ff..9eb7481 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ - 更多有用的功能 ## 下载 -任何版本都可以在 [Release](https://github.com/LuminolMC/LightingLuminol/releases), 中找到,你也可以通过[以下步骤](./README.md#构建)自己构建。 +任何版本都可以在 [Release](https://github.com/LuminolMC/Lophine/releases), 中找到,你也可以通过[以下步骤](./README.md#构建)自己构建。 ## 构建 -要构建一个paperclip jar,你需要运行以下命令。你可以在lightingluminol-server/build/libs中找到jar(注意:需要`JDK21`) +要构建一个paperclip jar,你需要运行以下命令。你可以在lophine-server/build/libs中找到jar(注意:需要`JDK21`) ```shell ./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar ``` diff --git a/README_EN.md b/README_EN.md index c13d596..ee46b9c 100644 --- a/README_EN.md +++ b/README_EN.md @@ -20,10 +20,10 @@ - More functions ## Download -Any versions are available in the [release](https://github.com/LuminolMC/LightingLuminol/releases), also you can build it by yourself through [the following steps](./README_EN.md#Build). +Any versions are available in the [release](https://github.com/LuminolMC/Lophine/releases), also you can build it by yourself through [the following steps](./README_EN.md#Build). ## Build -To build a paperclip jar, you need to run the following command. You can find the jar in build/libs(Note: JDK21 is needed) +To build a paperclip jar, you need to run the following command. You can find the jar in lophine-server/build/libs(Note: `JDK21` is needed) ```shell ./gradlew applyAllPatches && ./gradlew createMojmapPaperclipJar ``` diff --git a/gradle.properties b/gradle.properties index aead16a..cd392af 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=me.earthme.lophine version=1.21.5-R0.1-SNAPSHOT mcVersion=1.21.5 -luminolRef=6eebbe4221f34bf65832b02af01814fc057206b6 +luminolRef=818e1132dfb8a9849b082f6adf767b66c7da8b31 org.gradle.configuration-cache=true org.gradle.caching=true 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 caa0ab2..b645ee4 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 0814ad6820b08a856f7bd261e96143568e772ac4..b7ef7df56e94b6af9398d0a4768747a35ac6f4fd 100644 +index a023cc399fc8bfee7771e5ca6716578f89b7072f..f487b44174678196e2bade0066511daf58e93876 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; @@ -30,7 +30,7 @@ index 0814ad6820b08a856f7bd261e96143568e772ac4..b7ef7df56e94b6af9398d0a4768747a3 // CraftBukkit start private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); private static final int CURRENT_LEVEL = 2; -@@ -6107,4 +6107,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -6106,4 +6106,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper end - Expose entity id counter public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG diff --git a/lophine-server/minecraft-patches/features/0013-I18n-support.patch b/lophine-server/minecraft-patches/features/0013-I18n-support.patch index 1fca81f..2d298da 100644 --- a/lophine-server/minecraft-patches/features/0013-I18n-support.patch +++ b/lophine-server/minecraft-patches/features/0013-I18n-support.patch @@ -5,67 +5,27 @@ Subject: [PATCH] I18n support diff --git a/net/minecraft/locale/Language.java b/net/minecraft/locale/Language.java -index 7b9e2a1a208b46a69c16e6afd8b502259893574f..cdd26bbc6f6ff5510347049706e0f6f344fe79b1 100644 +index 7b9e2a1a208b46a69c16e6afd8b502259893574f..e2a42996bb01c99fc71a5994e8eeb66ce836af34 100644 --- a/net/minecraft/locale/Language.java +++ b/net/minecraft/locale/Language.java -@@ -31,11 +31,27 @@ public abstract class Language { +@@ -31,7 +31,7 @@ public abstract class Language { public static final String DEFAULT = "en_us"; private static volatile Language instance = loadDefault(); -+ // Lophine start - I18n support - private static Language loadDefault() { -+ return load("/assets/minecraft/lang/" + DEFAULT + ".json"); -+ } -+ -+ public static void loadLocalLang(String lang) { -+ try { -+ inject(load(lang)); -+ } catch (Exception e) { -+ LOGGER.error("Failed to load language file for {}", me.earthme.lophine.config.modules.optimizations.LanguageConfig.lang, e); -+ inject(loadDefault()); -+ } -+ } -+ -+ // Lophine end - I18n support -+ -+ private static Language load(String lang) { // Lophine - I18n support +- private static Language loadDefault() { ++ public static Language loadDefault() { // Lophine - I18n support DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource(); Map map = new HashMap<>(); BiConsumer biConsumer = map::put; -- parseTranslations(biConsumer, "/assets/minecraft/lang/en_us.json"); -+ parseTranslations(biConsumer, lang); // Lophine - I18n support - deprecatedTranslationsInfo.applyToMap(map); - final Map map1 = Map.copyOf(map); - return new Language() { -@@ -65,13 +81,26 @@ public abstract class Language { +@@ -65,7 +65,7 @@ public abstract class Language { }; } -+ // Lophine start - I18n support - private static void parseTranslations(BiConsumer output, String languagePath) { +- private static void parseTranslations(BiConsumer output, String languagePath) { ++ public static void parseTranslations(BiConsumer output, String languagePath) { // Lophine - I18n support try (InputStream resourceAsStream = Language.class.getResourceAsStream(languagePath)) { loadFromJson(resourceAsStream, output); -- } catch (JsonParseException | IOException var7) { -- LOGGER.error("Couldn't read strings from {}", languagePath, var7); -+ } catch (Exception e) { -+ try { -+ java.nio.file.Path filePath = java.nio.file.Paths.get(languagePath); -+ try (InputStream fileStream = java.nio.file.Files.newInputStream(filePath)) { -+ loadFromJson(fileStream, output); -+ } catch (java.nio.file.NoSuchFileException fileEx) { -+ LOGGER.error("Language file not found in both locations: {}", languagePath); -+ } catch (Exception fileEx) { -+ LOGGER.error("Failed to load from filesystem {}", filePath, fileEx); -+ } -+ } catch (Exception ep) { -+ LOGGER.error("Couldn't read strings from {}", languagePath, ep); -+ } - } - } -+ // Lophine end - I18n support - - public static void loadFromJson(InputStream stream, BiConsumer output) { - JsonObject jsonObject = GSON.fromJson(new InputStreamReader(stream, StandardCharsets.UTF_8), JsonObject.class); + } catch (JsonParseException | IOException var7) { diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java index ba0cdba050cd3bf9231e15dd9543d34f37d9dae5..ce7d70afa524e5b8ea6f9de75d34c8f1eaa6ad72 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java diff --git a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/LocalLangUtil.java.patch b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/LocalLangUtil.java.patch index ee643db..9734f8e 100644 --- a/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/LocalLangUtil.java.patch +++ b/lophine-server/paper-patches/files/src/main/java/me/earthme/lophine/utils/LocalLangUtil.java.patch @@ -1,11 +1,18 @@ --- /dev/null +++ b/src/main/java/me/earthme/lophine/utils/LocalLangUtil.java -@@ -1,0 +_,156 @@ +@@ -1,0 +_,257 @@ +package me.earthme.lophine.utils; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; ++import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; ++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 java.io.ByteArrayInputStream; +import java.io.IOException; @@ -16,35 +23,47 @@ +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; -+import java.util.Objects; ++import java.util.*; +import java.util.concurrent.CompletableFuture; ++import java.util.function.BiConsumer; +import java.util.logging.Logger; + -+import static me.earthme.lophine.config.modules.optimizations.LanguageConfig.lang; -+ +public class LocalLangUtil { -+ static Logger logger = Logger.getLogger("LangLoader"); -+ static String VERSION = "1.21.5"; -+ static String basePath = "cache/lophine/" + VERSION + "/"; ++ final static Logger logger = Logger.getLogger("LangLoader"); ++ final static String VERSION = "1.21.5"; ++ final static String basePath = "cache/lophine/" + VERSION + "/"; ++ static String lang = me.earthme.lophine.config.modules.optimizations.LanguageConfig.lang; ++ static boolean isReloading = false; + + public static void init() { + if (Objects.equals(lang, "en_us")) return; + CompletableFuture.runAsync(() -> { + try { -+ downloadLangAndCheck(); -+ net.minecraft.locale.Language.loadLocalLang(basePath + "lang/" + lang + ".json"); ++ String path = basePath + "lang/" + lang + ".json"; ++ if (!Files.exists(Path.of(path))) downloadLangAndCheck(); ++ try { ++ loadLocalLang(path); ++ isReloading = false; ++ } catch (JsonParseException e) { ++ cleanCache(); ++ if (!isReloading) { ++ isReloading = true; ++ init(); ++ } ++ } + } catch (Exception e) { + logger.severe(() -> "Async initialization failed: " + e.getMessage()); ++ isReloading = false; + } + }); + } + + private static void downloadLangAndCheck() { -+ Path path = Paths.get(basePath + VERSION + ".json"); ++ String path = basePath + VERSION + ".json"; + JsonObject json; -+ if (Files.exists(path)) { ++ if (Files.exists(Path.of(path))) { + try { -+ json = loadJson(path.toString()); ++ json = loadJson(path); + } catch (Exception e) { + logger.warning("Failed to load local JSON: " + e.getMessage()); + json = download(); @@ -152,8 +171,90 @@ + return data; + } + ++ private static void cleanCache() { ++ Path cachePath = Paths.get(basePath); ++ try { ++ if (Files.exists(cachePath)) { ++ Files.walk(cachePath) ++ .sorted(Comparator.reverseOrder()) ++ .forEach(path -> { ++ try { ++ Files.deleteIfExists(path); ++ } catch (IOException e) { ++ logger.warning("Failed to delete: " + path + " - " + e.getMessage()); ++ } ++ }); ++ logger.info("Cache cleaned: " + cachePath); ++ } else { ++ logger.info("Cache directory does not exist: " + cachePath); ++ } ++ } catch (IOException e) { ++ logger.severe("Cache cleanup failed: " + e.getMessage()); ++ } ++ } ++ ++ + public static JsonObject loadJson(String path) throws IOException { + byte[] data = Files.readAllBytes(Paths.get(path)); + return JsonParser.parseString(new String(data)).getAsJsonObject(); + } ++ ++ public static void loadLocalLang(String lang) { ++ try { ++ Language.inject(load(lang)); ++ } catch (Exception e) { ++ logger.warning("Failed to load language file for " + lang + "\n" + e); ++ Language.inject(Language.loadDefault()); ++ } ++ } ++ ++ private static Language load(String lang) { ++ DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource(); ++ Map map = new HashMap<>(); ++ BiConsumer biConsumer = map::put; ++ Language.parseTranslations(biConsumer, "/assets/minecraft/lang/en_us.json"); ++ parseTranslations(biConsumer, lang); ++ deprecatedTranslationsInfo.applyToMap(map); ++ final Map map1 = Map.copyOf(map); ++ return new Language() { ++ @Override ++ public String getOrDefault(String key, String defaultValue) { ++ return map1.getOrDefault(key, defaultValue); ++ } ++ ++ @Override ++ public boolean has(String id) { ++ return map1.containsKey(id); ++ } ++ ++ @Override ++ public boolean isDefaultRightToLeft() { ++ return false; ++ } ++ ++ @Override ++ public FormattedCharSequence getVisualOrder(FormattedText text) { ++ return sink -> text.visit( ++ (style, content) -> StringDecomposer.iterateFormatted(content, style, sink) ? Optional.empty() : FormattedText.STOP_ITERATION, ++ Style.EMPTY ++ ) ++ .isPresent(); ++ } ++ }; ++ } ++ ++ public static void parseTranslations(BiConsumer output, String languagePath) { ++ try { ++ java.nio.file.Path filePath = java.nio.file.Paths.get(languagePath); ++ try (InputStream fileStream = java.nio.file.Files.newInputStream(filePath)) { ++ Language.loadFromJson(fileStream, output); ++ } catch (java.nio.file.NoSuchFileException fileEx) { ++ logger.warning("Language file not found in both locations: " + languagePath); ++ } catch (Exception fileEx) { ++ logger.warning("Failed to load from filesystem " + filePath + "\n" + fileEx); ++ } ++ } catch (Exception ep) { ++ logger.warning("Couldn't read strings from " + languagePath + "\n" + ep); ++ } ++ } +}