diff --git a/arclight-common/build.gradle b/arclight-common/build.gradle index b1134ea9..0578b798 100644 --- a/arclight-common/build.gradle +++ b/arclight-common/build.gradle @@ -60,6 +60,7 @@ dependencies { compile 'mysql:mysql-connector-java:5.1.47' compile 'org.yaml:snakeyaml:1.23' compile project(':arclight-api') + compile project(':i18n-config') } remapSpigotJar { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/JavaPluginMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/JavaPluginMixin.java index b911cd30..38a3313c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/JavaPluginMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/JavaPluginMixin.java @@ -1,12 +1,12 @@ package io.izzel.arclight.common.mixin.bukkit; +import io.izzel.arclight.common.mod.util.log.ArclightPluginLogger; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginLogger; import org.bukkit.plugin.java.JavaPlugin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import io.izzel.arclight.common.mod.util.ArclightPluginLogger; @Mixin(JavaPlugin.class) public class JavaPluginMixin { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java index 54c69302..9a73ae28 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java @@ -128,10 +128,10 @@ public abstract class PlayerListMixin implements PlayerListBridge { t.printStackTrace(); } try { - ArclightMod.LOGGER.info("Registering for bukkit... "); + ArclightMod.LOGGER.info("registry.begin"); BukkitRegistry.registerAll(); } catch (Throwable t) { - ArclightMod.LOGGER.error("Error handling Forge registries ", t); + ArclightMod.LOGGER.error("registry.error", t); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConfig.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConfig.java deleted file mode 100644 index d2689e39..00000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.izzel.arclight.common.mod; - -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; - -public class ArclightConfig { - - public static ArclightConfig INSTANCE; - - public Optimization optimizations; - - static void init(Path path) { - ArclightConnector.LOGGER.info("Loading configurations from {}", path); - try { - if (!Files.exists(path)) { - InputStream stream = ArclightConfig.class.getResourceAsStream("/arclight.yml"); - Files.copy(stream, path); - } - } catch (IOException e) { - ArclightConnector.LOGGER.error("Failed to save default configurations", e); - } - try { - Yaml yaml = new Yaml(new Constructor(ArclightConfig.class)); - Object load = yaml.load(Files.newInputStream(path)); - INSTANCE = (ArclightConfig) load; - } catch (IOException e) { - ArclightConnector.LOGGER.error("Failed to load configurations", e); - } - } - - public static class Optimization { - - public boolean removeStreams = true; - - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConnector.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConnector.java index b03eb54b..ed10532e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConnector.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConnector.java @@ -1,27 +1,33 @@ package io.izzel.arclight.common.mod; -import org.apache.logging.log4j.LogManager; +import cpw.mods.modlauncher.api.ITransformingClassLoader; +import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger; +import io.izzel.arclight.i18n.ArclightConfig; import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.Mixins; import org.spongepowered.asm.mixin.connect.IMixinConnector; -import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; public class ArclightConnector implements IMixinConnector { - public static final Logger LOGGER = LogManager.getLogger("Arclight"); + public static final Logger LOGGER = ArclightI18nLogger.getLogger("Arclight"); + private static final List FILTER_PACKAGE = Arrays.asList("com.google.common", "com.google.gson", "ninja.leaping.configurate"); @Override public void connect() { + ((ITransformingClassLoader) Thread.currentThread().getContextClassLoader()).addTargetPackageFilter( + s -> FILTER_PACKAGE.stream().noneMatch(s::startsWith) + ); Mixins.addConfiguration("mixins.arclight.core.json"); Mixins.addConfiguration("mixins.arclight.bukkit.json"); Mixins.addConfiguration("mixins.arclight.forge.json"); - LOGGER.info("Arclight core mixin added."); - ArclightConfig.init(Paths.get("arclight.yml")); + LOGGER.info("mixin-load.core"); Mixins.addConfiguration("mixins.arclight.optimization.json"); - if (ArclightConfig.INSTANCE.optimizations.removeStreams) { + if (ArclightConfig.spec().getOptimization().isRemoveStream()) { Mixins.addConfiguration("mixins.arclight.optimization.stream.json"); } - LOGGER.info("Arclight optimization mixin added."); + LOGGER.info("mixin-load.optimization"); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightLocator.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightLocator.java index 9641e61e..d8317659 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightLocator.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightLocator.java @@ -4,8 +4,6 @@ import com.google.common.collect.ImmutableList; import net.minecraftforge.fml.loading.moddiscovery.AbstractJarFileLocator; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.forgespi.locating.IModFile; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.io.File; import java.net.URISyntaxException; @@ -14,8 +12,6 @@ import java.util.Map; public class ArclightLocator extends AbstractJarFileLocator { - private static final Logger LOGGER = LogManager.getLogger("Arclight"); - private final IModFile arclight; public ArclightLocator() { @@ -39,6 +35,5 @@ public class ArclightLocator extends AbstractJarFileLocator { @Override public void initArguments(Map arguments) { - LOGGER.info("Arclight locator loaded."); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java index db9ba0f5..cc6d9834 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMod.java @@ -1,23 +1,23 @@ package io.izzel.arclight.common.mod; import io.izzel.arclight.common.mod.server.event.ArclightEventDispatcherRegistry; +import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger; import net.minecraftforge.fml.CrashReportExtender; import net.minecraftforge.fml.ExtensionPoint; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.network.FMLNetworkConstants; import org.apache.commons.lang3.tuple.Pair; -import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.v.CraftCrashReport; @Mod("arclight") public class ArclightMod { - public static final Logger LOGGER = LogManager.getLogger("Arclight"); + public static final Logger LOGGER = ArclightI18nLogger.getLogger("Arclight"); public ArclightMod() { - LOGGER.info("Arclight Mod loaded."); + LOGGER.info("mod-load"); ArclightEventDispatcherRegistry.registerAllEventDispatchers(); CrashReportExtender.registerCrashCallable("Arclight", () -> new CraftCrashReport().call().toString()); ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true)); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java index d510e674..8511ae35 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java @@ -2,6 +2,11 @@ package io.izzel.arclight.common.mod.server; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import io.izzel.arclight.api.EnumHelper; +import io.izzel.arclight.api.Unsafe; +import io.izzel.arclight.common.bridge.bukkit.MaterialBridge; +import io.izzel.arclight.common.mod.ArclightMod; +import io.izzel.arclight.common.mod.util.potion.ArclightPotionEffect; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.potion.Effect; @@ -15,11 +20,6 @@ import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.bukkit.craftbukkit.v.util.CraftNamespacedKey; import org.bukkit.enchantments.Enchantment; import org.bukkit.potion.PotionEffectType; -import io.izzel.arclight.common.bridge.bukkit.MaterialBridge; -import io.izzel.arclight.common.mod.ArclightMod; -import io.izzel.arclight.common.mod.util.potion.ArclightPotionEffect; -import io.izzel.arclight.api.EnumHelper; -import io.izzel.arclight.api.Unsafe; import java.lang.reflect.Field; import java.util.ArrayList; @@ -31,12 +31,12 @@ import java.util.Set; @SuppressWarnings({"unchecked", "ConstantConditions"}) public class BukkitRegistry { - private static List> MAT_CTOR = ImmutableList.of(int.class, int.class, int.class); - private static Map BY_NAME = getStatic(Material.class, "BY_NAME"); - private static Map BLOCK_MATERIAL = getStatic(CraftMagicNumbers.class, "BLOCK_MATERIAL"); - private static Map ITEM_MATERIAL = getStatic(CraftMagicNumbers.class, "ITEM_MATERIAL"); - private static Map MATERIAL_ITEM = getStatic(CraftMagicNumbers.class, "MATERIAL_ITEM"); - private static Map MATERIAL_BLOCK = getStatic(CraftMagicNumbers.class, "MATERIAL_BLOCK"); + private static final List> MAT_CTOR = ImmutableList.of(int.class, int.class, int.class); + private static final Map BY_NAME = getStatic(Material.class, "BY_NAME"); + private static final Map BLOCK_MATERIAL = getStatic(CraftMagicNumbers.class, "BLOCK_MATERIAL"); + private static final Map ITEM_MATERIAL = getStatic(CraftMagicNumbers.class, "ITEM_MATERIAL"); + private static final Map MATERIAL_ITEM = getStatic(CraftMagicNumbers.class, "MATERIAL_ITEM"); + private static final Map MATERIAL_BLOCK = getStatic(CraftMagicNumbers.class, "MATERIAL_BLOCK"); public static void registerAll() { loadMaterials(); @@ -52,7 +52,7 @@ public class BukkitRegistry { Enchantment.registerEnchantment(new CraftEnchantment(entry.getValue())); } Enchantment.stopAcceptingRegistrations(); - ArclightMod.LOGGER.info("Registered {} new enchantments", size - origin); + ArclightMod.LOGGER.info("registry.enchantment", size - origin); } private static void loadPotions() { @@ -68,7 +68,7 @@ public class BukkitRegistry { ArclightMod.LOGGER.debug("Registered {}: {} as potion", entry.getKey(), effect); } PotionEffectType.stopAcceptingRegistrations(); - ArclightMod.LOGGER.info("Registered {} new potion effect types", size - origin); + ArclightMod.LOGGER.info("registry.potion", size - origin); } private static void loadMaterials() { @@ -122,7 +122,7 @@ public class BukkitRegistry { ITEM_MATERIAL.put(item, material); MATERIAL_ITEM.put(material, item); } - ArclightMod.LOGGER.info("Registered {} new materials, with {} blocks and {} items", i - origin, blocks, items); + ArclightMod.LOGGER.info("registry.material", i - origin, blocks, items); } private static String toName(ResourceLocation location) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java index 2c74a62f..23bccc6b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java @@ -1,12 +1,11 @@ package io.izzel.arclight.common.mod.server.event; -import net.minecraftforge.common.MinecraftForge; import io.izzel.arclight.common.mod.ArclightMod; +import net.minecraftforge.common.MinecraftForge; public abstract class ArclightEventDispatcherRegistry { public static void registerAllEventDispatchers() { - ArclightMod.LOGGER.info("Arclight register all event dispatchers."); MinecraftForge.EVENT_BUS.register(new BlockBreakEventDispatcher()); MinecraftForge.EVENT_BUS.register(new BlockPlaceEventDispatcher()); MinecraftForge.EVENT_BUS.register(new EntityPotionEffectEventDispatcher()); @@ -15,6 +14,7 @@ public abstract class ArclightEventDispatcherRegistry { MinecraftForge.EVENT_BUS.register(new NetworkEventDispatcher()); MinecraftForge.EVENT_BUS.register(new EntityTeleportEventDispatcher()); MinecraftForge.EVENT_BUS.register(new ItemEntityEventDispatcher()); + ArclightMod.LOGGER.info("registry.forge-event"); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightI18nLogger.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightI18nLogger.java new file mode 100644 index 00000000..3fa1a42f --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightI18nLogger.java @@ -0,0 +1,113 @@ +package io.izzel.arclight.common.mod.util.log; + +import io.izzel.arclight.i18n.ArclightLocale; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.spi.ExtendedLogger; +import org.apache.logging.log4j.spi.ExtendedLoggerWrapper; +import org.apache.logging.log4j.util.MessageSupplier; +import org.apache.logging.log4j.util.Supplier; + +public class ArclightI18nLogger extends ExtendedLoggerWrapper { + + public ArclightI18nLogger(ExtendedLogger logger) { + super(logger, logger.getName(), logger.getMessageFactory()); + } + + public static Logger getLogger(String name) { + return new ArclightI18nLogger((ExtendedLogger) LogManager.getLogger(name)); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, CharSequence message, Throwable t) { + this.info("", ""); + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message.toString()), t); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, Object message, Throwable t) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message.toString()), t); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, MessageSupplier msgSupplier, Throwable t) { + super.logMessage(fqcn, level, marker, msgSupplier, t); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, Supplier msgSupplier, Throwable t) { + super.logMessage(fqcn, level, marker, msgSupplier, t); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Throwable t) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), t); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message)); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object... params) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), params); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4, p5); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4, p5, p6); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4, p5, p6, p7); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4, p5, p6, p7, p8); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + @Override + protected void logMessage(String fqcn, Level level, Marker marker, String message, Supplier... paramSuppliers) { + super.logMessage(fqcn, level, marker, ArclightLocale.getInstance().get(message), paramSuppliers); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLazyLogManager.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLazyLogManager.java new file mode 100644 index 00000000..0edacd95 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLazyLogManager.java @@ -0,0 +1,40 @@ +package io.izzel.arclight.common.mod.util.log; + +import java.util.Enumeration; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +public class ArclightLazyLogManager extends LogManager { + + private volatile LogManager delegate; + + @Override + public boolean addLogger(Logger logger) { + tryGet(); + if (delegate != null) return delegate.addLogger(logger); + return super.addLogger(logger); + } + + @Override + public Logger getLogger(String name) { + tryGet(); + if (delegate != null) return delegate.getLogger(name); + return super.getLogger(name); + } + + @Override + public Enumeration getLoggerNames() { + tryGet(); + if (delegate != null) return delegate.getLoggerNames(); + return super.getLoggerNames(); + } + + private void tryGet() { + if (delegate != null) return; + try { + Class name = Class.forName("org.apache.logging.log4j.jul.LogManager"); + delegate = (LogManager) name.newInstance(); + } catch (Exception ignored) { + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightLoggerAdapter.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLoggerAdapter.java similarity index 99% rename from arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightLoggerAdapter.java rename to arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLoggerAdapter.java index 22cae003..8f51fe51 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightLoggerAdapter.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightLoggerAdapter.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mod.util; +package io.izzel.arclight.common.mod.util.log; import org.apache.logging.log4j.jul.ApiLogger; import org.apache.logging.log4j.jul.CoreLoggerAdapter; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightPluginLogger.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightPluginLogger.java similarity index 92% rename from arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightPluginLogger.java rename to arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightPluginLogger.java index c33dfa20..18101c56 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightPluginLogger.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/log/ArclightPluginLogger.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mod.util; +package io.izzel.arclight.common.mod.util.log; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginLogger; diff --git a/arclight-forge-1.14/build.gradle b/arclight-forge-1.14/build.gradle index 18b94e59..aaba13a3 100644 --- a/arclight-forge-1.14/build.gradle +++ b/arclight-forge-1.14/build.gradle @@ -69,6 +69,7 @@ dependencies { minecraft "net.minecraftforge:forge:$minecraftVersion-$forgeVersion" compile group: 'org.jetbrains', name: 'annotations', version: '19.0.0' compile project(':arclight-common') + embed project(':i18n-config') embed project(':forge-installer') for (def lib : embedLibs) { arclight lib diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java index 1227657c..69d0fc17 100644 --- a/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java @@ -1,17 +1,23 @@ package io.izzel.arclight.server; -import io.izzel.arclight.api.Unsafe; -import io.izzel.arclight.forgeinstaller.ForgeInstaller; -import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper; import io.izzel.arclight.api.EnumHelper; +import io.izzel.arclight.api.Unsafe; +import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger; +import io.izzel.arclight.common.mod.util.log.ArclightLazyLogManager; +import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper; +import io.izzel.arclight.forgeinstaller.ForgeInstaller; +import io.izzel.arclight.i18n.ArclightConfig; +import io.izzel.arclight.i18n.ArclightLocale; import net.minecraftforge.server.ServerMain; -import org.apache.logging.log4j.LogManager; import java.util.Objects; public class Main { public static void main(String[] args) throws Throwable { + System.setProperty("java.util.logging.manager", ArclightLazyLogManager.class.getCanonicalName()); + System.setProperty("log4j.jul.LoggerAdapter", "io.izzel.arclight.common.mod.util.log.ArclightLoggerAdapter"); + ArclightLocale.info("i18n.using-language", ArclightConfig.spec().getLocale().getCurrent(), ArclightConfig.spec().getLocale().getFallback()); ForgeInstaller.install(); try { // Java 9 & Java 兼容性 int javaVersion = (int) Float.parseFloat(System.getProperty("java.class.version")); @@ -25,9 +31,7 @@ public class Main { return; } try { - System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager"); - System.setProperty("log4j.jul.LoggerAdapter", "io.izzel.arclight.common.mod.util.ArclightLoggerAdapter"); - LogManager.getLogger("Arclight").info("Loading mappings ..."); + ArclightI18nLogger.getLogger("Arclight").info("loading-mapping"); Objects.requireNonNull(ArclightRemapper.INSTANCE); ServerMain.main(args); } catch (Exception e) { diff --git a/i18n-config/build.gradle b/i18n-config/build.gradle new file mode 100644 index 00000000..0caedf54 --- /dev/null +++ b/i18n-config/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +repositories { + mavenCentral() + maven { + name = 'sponge' + url = 'https://repo.spongepowered.org/maven' + } +} + +dependencies { + compile 'org.spongepowered:configurate-hocon:3.6.1' +} + +jar { + from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) +} diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightConfig.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightConfig.java new file mode 100644 index 00000000..a0a66700 --- /dev/null +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightConfig.java @@ -0,0 +1,91 @@ +package io.izzel.arclight.i18n; + +import com.google.common.reflect.TypeToken; +import io.izzel.arclight.i18n.conf.ConfigSpec; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.commented.CommentedConfigurationNode; +import ninja.leaping.configurate.hocon.HoconConfigurationLoader; +import ninja.leaping.configurate.objectmapping.ObjectMappingException; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.StringJoiner; + +public class ArclightConfig { + + private static ArclightConfig instance; + + private final CommentedConfigurationNode node; + private final ConfigSpec spec; + + public ArclightConfig(CommentedConfigurationNode node) throws ObjectMappingException { + this.node = node; + this.spec = this.node.getValue(TypeToken.of(ConfigSpec.class)); + } + + public CommentedConfigurationNode getNode() { + return node; + } + + public ConfigSpec getSpec() { + return spec; + } + + public ConfigurationNode get(String path) { + return this.node.getNode((Object[]) path.split("\\.")); + } + + public static ConfigSpec spec() { + return instance.spec; + } + + private static void load() throws Exception { + Path path = Paths.get("arclight.conf"); + CommentedConfigurationNode node = HoconConfigurationLoader.builder().setSource( + () -> new BufferedReader(new InputStreamReader(ArclightConfig.class.getResourceAsStream("/META-INF/arclight.conf"), StandardCharsets.UTF_8)) + ).build().load(); + HoconConfigurationLoader loader = HoconConfigurationLoader.builder().setPath(path).build(); + CommentedConfigurationNode cur = loader.load(); + cur.mergeValuesFrom(node); + cur.getNode("locale", "current").setValue(ArclightLocale.getInstance().getCurrent()); + fillComments(cur, ArclightLocale.getInstance()); + instance = new ArclightConfig(cur); + loader.save(cur); + } + + private static void fillComments(CommentedConfigurationNode node, ArclightLocale locale) { + if (!node.getComment().isPresent()) { + String path = pathOf(node); + Optional option = locale.getOption("comments." + path + ".comment"); + option.ifPresent(node::setComment); + } + if (node.hasMapChildren()) { + for (CommentedConfigurationNode value : node.getChildrenMap().values()) { + fillComments(value, locale); + } + } + } + + private static String pathOf(ConfigurationNode node) { + StringJoiner joiner = new StringJoiner("."); + for (Object o : node.getPath()) { + if (o != null) { + joiner.add(o.toString()); + } + } + String s = joiner.toString(); + return s.isEmpty() ? "__root__" : s; + } + + static { + try { + load(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightLocale.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightLocale.java new file mode 100644 index 00000000..e952d8ea --- /dev/null +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/ArclightLocale.java @@ -0,0 +1,132 @@ +package io.izzel.arclight.i18n; + +import ninja.leaping.configurate.ValueType; +import ninja.leaping.configurate.commented.CommentedConfigurationNode; +import ninja.leaping.configurate.hocon.HoconConfigurationLoader; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.AbstractMap; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.StringJoiner; +import java.util.concurrent.Callable; + +public class ArclightLocale { + + private static ArclightLocale instance; + + private final String current, fallback; + private final CommentedConfigurationNode node; + + public ArclightLocale(String current, String fallback, CommentedConfigurationNode node) { + this.current = current; + this.fallback = fallback; + this.node = node; + } + + public String getCurrent() { + return current; + } + + public String getFallback() { + return fallback; + } + + public CommentedConfigurationNode getNode() { + return node; + } + + public String format(String node, Object... args) { + return MessageFormat.format(get(node), args); + } + + public String get(String path) { + return getOption(path).orElse(path); + } + + public Optional getOption(String path) { + CommentedConfigurationNode node = this.node.getNode((Object[]) path.split("\\.")); + if (node.getValueType() == ValueType.LIST) { + StringJoiner joiner = new StringJoiner("\n"); + for (CommentedConfigurationNode configurationNode : node.getChildrenList()) { + joiner.add(configurationNode.getString()); + } + return Optional.ofNullable(joiner.toString()); + } else { + return Optional.ofNullable(node.getString()); + } + } + + public static void info(String path, Object... args) { + System.out.println(instance.format(path, args)); + } + + public static void error(String path, Object... args) { + System.err.println(instance.format(path, args)); + } + + public static ArclightLocale getInstance() { + return instance; + } + + private static void init() throws Exception { + Map.Entry entry = getLocale(); + String current = entry.getKey(); + String fallback = entry.getValue(); + InputStream stream = ArclightLocale.class.getResourceAsStream("/META-INF/i18n/" + fallback + ".conf"); + if (stream == null) throw new RuntimeException("Fallback locale is not found: " + fallback); + CommentedConfigurationNode node = HoconConfigurationLoader.builder().setSource(localeSource(fallback)).build().load(); + instance = new ArclightLocale(current, fallback, node); + if (!current.equals(fallback)) { + try { + CommentedConfigurationNode curNode = HoconConfigurationLoader.builder().setSource(localeSource(current)).build().load(); + curNode.mergeValuesFrom(node); + instance = new ArclightLocale(current, fallback, curNode); + } catch (Exception e) { + System.err.println(instance.format("i18n.current-not-available", current)); + } + } + } + + private static Callable localeSource(String path) { + return () -> new BufferedReader(new InputStreamReader(ArclightLocale.class.getResourceAsStream("/META-INF/i18n/" + path + ".conf"), StandardCharsets.UTF_8)); + } + + private static Map.Entry getLocale() { + try { + Path path = Paths.get("arclight.conf"); + if (!Files.exists(path)) { + throw new Exception(); + } else { + CommentedConfigurationNode node = HoconConfigurationLoader.builder().setPath(path).build().load(); + CommentedConfigurationNode locale = node.getNode("locale"); + String current = locale.getNode("current").getString(currentLocale()); + String fallback = locale.getNode("fallback").getString("zh_cn"); + return new AbstractMap.SimpleImmutableEntry<>(current, fallback); + } + } catch (Throwable t) { + return new AbstractMap.SimpleImmutableEntry<>(currentLocale(), "zh_cn"); + } + } + + private static String currentLocale() { + Locale locale = Locale.getDefault(); + return locale.getLanguage().toLowerCase(Locale.ROOT) + "_" + locale.getCountry().toLowerCase(Locale.ROOT); + } + + static { + try { + init(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/ConfigSpec.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/ConfigSpec.java new file mode 100644 index 00000000..f56ed69a --- /dev/null +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/ConfigSpec.java @@ -0,0 +1,29 @@ +package io.izzel.arclight.i18n.conf; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class ConfigSpec { + + @Setting("_v") + private int version; + + @Setting("optimization") + private OptimizationSpec optimizationSpec; + + @Setting("locale") + private LocaleSpec localeSpec; + + public int getVersion() { + return version; + } + + public OptimizationSpec getOptimization() { + return optimizationSpec; + } + + public LocaleSpec getLocale() { + return localeSpec; + } +} diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/LocaleSpec.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/LocaleSpec.java new file mode 100644 index 00000000..ae3a613a --- /dev/null +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/LocaleSpec.java @@ -0,0 +1,22 @@ +package io.izzel.arclight.i18n.conf; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class LocaleSpec { + + @Setting("current") + private String current; + + @Setting("fallback") + private String fallback; + + public String getCurrent() { + return current; + } + + public String getFallback() { + return fallback; + } +} diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/OptimizationSpec.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/OptimizationSpec.java new file mode 100644 index 00000000..a0ed7ad9 --- /dev/null +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/OptimizationSpec.java @@ -0,0 +1,15 @@ +package io.izzel.arclight.i18n.conf; + +import ninja.leaping.configurate.objectmapping.Setting; +import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; + +@ConfigSerializable +public class OptimizationSpec { + + @Setting("remove-stream") + private boolean removeStream; + + public boolean isRemoveStream() { + return removeStream; + } +} diff --git a/i18n-config/src/main/resources/META-INF/arclight.conf b/i18n-config/src/main/resources/META-INF/arclight.conf new file mode 100644 index 00000000..ae1ce797 --- /dev/null +++ b/i18n-config/src/main/resources/META-INF/arclight.conf @@ -0,0 +1,8 @@ +_v = 1 + +locale { + fallback = "zh_cn" +} +optimization { + remove-stream = true +} diff --git a/i18n-config/src/main/resources/META-INF/i18n/en_us.conf b/i18n-config/src/main/resources/META-INF/i18n/en_us.conf new file mode 100644 index 00000000..ccc5bb4e --- /dev/null +++ b/i18n-config/src/main/resources/META-INF/i18n/en_us.conf @@ -0,0 +1,29 @@ +i18n { + current-not-available = "Current locale {0} is not available" + using-language = "Using locale {0} and fallback locale {1}" +} +loading-mapping = "Loading mappings ..." +mixin-load { + core = "Arclight core mixin added." + optimization = "Arclight optimization mixin added." +} +mod-load = "Arclight Mod loaded." +registry { + forge-event = "Arclight events registered." + begin = "Regitring for Bukkit ..." + error = "Error occured registring Forge " + enchantment = "Registered {} enchantments" + potion = "Registered {} new potion effect types" + material = "Registered {} new materials with {} blocks and {} items" +} + +comments { + _v.comment = [ + "Repository: https://github.com/IzzelAliz/Arclight" + "Issue Tracker: https://github.com/IzzelAliz/Arclight/issues" + "" + "" + "Config version number, do not edit." + ] + locale.comment = "Language/I18n settings" +} diff --git a/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf b/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf new file mode 100644 index 00000000..46357ee4 --- /dev/null +++ b/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf @@ -0,0 +1,30 @@ +i18n { + current-not-available = "选择的语言 {0} 不可用" + using-language = "正在使用 {0} 语言,{1} 作为备选语言" +} +loading-mapping = "正在加载混淆数据 ..." +mixin-load { + core = "核心 Mixin 配置已加载" + optimization = "服务端优化 Mixin 配置已加载" +} +mod-load = "Arclight Mod 已加载" +registry { + forge-event = "Arclight 事件系统已注册" + begin = "正在向 Bukkit 注册 ..." + error = "处理 Forge 注册时出错 " + enchantment = "注册了 {} 个新的附魔" + potion = "注册了 {} 个新的药水效果" + material = "注册了 {} 个材料,其中 {} 个方块 {} 个物品" +} + +comments { + _v.comment = [ + "源代码仓库: https://github.com/IzzelAliz/Arclight" + "提交反馈/错误报告: https://github.com/IzzelAliz/Arclight/issues" + "" + "" + "配置文件版本号,请勿编辑" + ] + locale.comment = "语言/国际化相关设置" + optimization.comment = "服务端优化相关设置" +} diff --git a/settings.gradle b/settings.gradle index 032d5d02..c831eabb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,5 @@ include 'arclight-testplugin' include 'arclight-common' include 'forge-installer' include 'arclight-api' +include 'i18n-config'