diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 46b5e204e..cc52404bc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -7,8 +7,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dejvokep.boostedyaml.YamlDocument; -import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditCommandHelper; import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditBlockRegister; +import net.momirealms.craftengine.bukkit.block.worldedit.WorldEditCommandHelper; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.network.PacketConsumers; @@ -452,7 +452,18 @@ public class BukkitBlockManager extends AbstractBlockManager { // create block Map behaviorSection = MiscUtils.castToMap(section.getOrDefault("behavior", Map.of()), false); - CustomBlock block = new BukkitCustomBlock(id, holder, properties, appearances, variants, settings, behaviorSection, lootTable); + BukkitCustomBlock block = new BukkitCustomBlock(id, holder, properties, appearances, variants, settings, behaviorSection, lootTable); + // read block name + String blockName = (String) section.getOrDefault("name", null); + if (blockName != null && blockName.startsWith("i18n:")) { + plugin.translationManager().i18nData().forEach((locale, i18nData) -> { + plugin.debug(() -> "locale: " + toMinecraftLocale(locale) + ": " + i18nData.translate(blockName.substring(5))); + block.addBlockName(toMinecraftLocale(locale), i18nData.translate(blockName.substring(5))); + } + ); + } else { + block.addBlockName(blockName); + } // bind appearance bindAppearance(block); @@ -467,6 +478,18 @@ public class BukkitBlockManager extends AbstractBlockManager { } } + public static String toMinecraftLocale(Locale locale) { + String language = locale.getLanguage().toLowerCase(); + String country = locale.getCountry().toLowerCase(); + if ("en".equals(language) && country.isEmpty()) { + return "en_us"; + } + if (country.isEmpty()) { + return language; + } + return language + "_" + country; + } + private void bindAppearance(CustomBlock block) { for (ImmutableBlockState state : block.variantProvider().states()) { ImmutableBlockState previous = this.stateId2ImmutableBlockStates[state.customBlockState().registryId() - BlockStateUtils.vanillaStateSize()]; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index 1b89860b0..7437b832a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.block.*; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.locale.I18NData; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Tristate; @@ -137,4 +138,24 @@ public class BukkitCustomBlock extends CustomBlock { CraftEngine.instance().logger().warn("Failed to init block settings", e); } } + + public void addBlockName(String lang, String blockName) { + I18NData i18nData = new I18NData(); + for (ImmutableBlockState state : this.variantProvider().states()) { + try { + Object blockState = state.customBlockState().handle(); + Object block = Reflections.method$BlockStateBase$getBlock.invoke(blockState); + String translationKey = (String) Reflections.method$BlockBehaviour$getDescriptionId.invoke(block); + i18nData.addTranslation(translationKey, blockName); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to get the " + state.owner().value().id() + " translationKey"); + } + } + this.addBlockName(lang, i18nData); + } + + public void addBlockName(String blockName) { + if (blockName == null) return; + addBlockName("en_us", blockName); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index fa78c1e62..41d8af579 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -5528,4 +5528,16 @@ public class Reflections { ReflectionUtils.getMethod( clazz$ItemStack,new String[]{"b"}, clazz$Registry, clazz$BlockInWorld ); + + public static final Method method$BlockStateBase$getBlock = requireNonNull( + ReflectionUtils.getMethod( + clazz$BlockStateBase, clazz$Block + ) + ); + + public static final Method method$BlockBehaviour$getDescriptionId = requireNonNull( + VersionHelper.isVersionNewerThan1_21_2() + ? ReflectionUtils.getMethod(clazz$BlockBehaviour, String.class) + : ReflectionUtils.getMethod(clazz$Block, String.class) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java index 9a5199a8d..95c79dfad 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/CustomBlock.java @@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.locale.I18NData; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.shared.block.BlockBehavior; @@ -13,10 +14,7 @@ import net.momirealms.sparrow.nbt.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.BiFunction; public abstract class CustomBlock { @@ -29,6 +27,8 @@ public abstract class CustomBlock { protected final ImmutableBlockState defaultState; @Nullable protected final LootTable lootTable; + private Map blockName = new HashMap<>(); + public CustomBlock( @NotNull Key id, @@ -156,4 +156,19 @@ public abstract class CustomBlock { state = (ImmutableBlockState) this.behavior.updateStateForPlacement(context, state); return state; } + + public Map blockName() { + return blockName; + } + + public void addBlockName(String lang, I18NData i18NData) { + if (this.blockName == null) { + this.blockName = new HashMap<>(); + } + this.blockName.put(lang, i18NData); + } + + public void setBlockName(Map blockName) { + this.blockName = blockName; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java index 29cc9fe41..b6bd0310f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/ClientLangMangerImpl.java @@ -67,6 +67,12 @@ public class ClientLangMangerImpl implements ClientLangManager { @Override public Map langData() { + this.plugin.blockManager().blocks().forEach((key, block) -> { + Map blockName = block.blockName(); + if (blockName != null) { + I18NData.merge(i18nData, blockName); + } + }); return Collections.unmodifiableMap(i18nData); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/I18NData.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/I18NData.java index 9c05a8f43..febcbe746 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/I18NData.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/I18NData.java @@ -20,4 +20,20 @@ public class I18NData { public String translate(String key) { return this.translations.get(key); } + + @Override + public String toString() { + return "I18NData{" + translations + "}"; + } + + public static void merge(Map target, Map source) { + source.forEach((key, value) -> { + I18NData copy = new I18NData(); + copy.addTranslations(value.translations); + target.merge(key, copy, (existing, newData) -> { + existing.addTranslations(newData.translations); + return existing; + }); + }); + } } \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java index cb8ec17e6..637fb75e9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManager.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser; import org.jetbrains.annotations.Nullable; import java.util.Locale; +import java.util.Map; public interface TranslationManager extends Reloadable, ConfigSectionParser { String CONFIG_SECTION_NAME = "i18n"; @@ -38,6 +39,8 @@ public interface TranslationManager extends Reloadable, ConfigSectionParser { return locale == null || locale.isEmpty() ? null : Translator.parseLocale(locale); } + Map i18nData(); + @Override default int loadingSequence() { return LoadingSequence.TRANSLATION; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java index 6c1640fde..43f99aa67 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/TranslationManagerImpl.java @@ -277,4 +277,9 @@ public class TranslationManagerImpl implements TranslationManager { return newFileContents; } } + + @Override + public Map i18nData() { + return Collections.unmodifiableMap(this.i18nData); + } }