Skip to content

Commit

Permalink
Merge pull request #7 from HiedaCamellia/feat/data-generator
Browse files Browse the repository at this point in the history
本地化文本的自动生成
  • Loading branch information
Yuqi154 authored Apr 30, 2024
2 parents 6cb6349 + 9913170 commit f74bf29
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 23 deletions.
46 changes: 36 additions & 10 deletions src/main/java/com/gensokyo/nucleardelight/NuclearDelight.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gensokyo.nucleardelight;

import com.gensokyo.nucleardelight.datagenerator.LangName;
import com.gensokyo.nucleardelight.register.AutoRegistryObject;
import com.gensokyo.nucleardelight.world.effect.MobEffects;
import com.gensokyo.nucleardelight.world.food.Foods;
Expand Down Expand Up @@ -33,9 +34,9 @@
import net.minecraftforge.registries.RegistryObject;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Supplier;

// The value here should match an entry in the META-INF/mods.toml file
@Mod(NuclearDelight.MODID)
Expand Down Expand Up @@ -70,6 +71,8 @@ public class NuclearDelight {
output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event
}).build());

public static Map<String, Map<Supplier<String>, String>> LangKeyValuePairs = new HashMap<>();

public static List<RegistryObject<Item>> RegisteredItems = new ArrayList<>();

public NuclearDelight() {
Expand All @@ -78,14 +81,27 @@ public NuclearDelight() {
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);

List<RegistryObject<Item>> registeredFoods = Utils.registryObjects(ITEMS,
Utils.getStaticFinalFieldsNameAndValue(Foods.class, FoodProperties.class).entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().toLowerCase(),
entry -> () -> new Item(new Item.Properties().food(entry.getValue()))
)));
Field[] foodFields = Utils.getStaticFinalFields(Foods.class, FoodProperties.class);

// List<RegistryObject<Item>> registeredFoods = Utils.registryObjects(ITEMS,
// Utils.getStaticFinalFieldsNameAndValueFrom(Foods.class, FoodProperties.class).entrySet().stream()
// .collect(Collectors.toMap(
// entry -> entry.getKey().toLowerCase(),
// entry -> () -> new Item(new Item.Properties().food(entry.getValue()))
// )));

List<RegistryObject<Item>> registeredFoods = Arrays.stream(foodFields)
.map(field -> {
Map.Entry<String, FoodProperties> entry = Utils.getNameAndValueFromField(field);
return ITEMS.register(field.getName().toLowerCase(), () -> new Item(new Item.Properties().food(entry.getValue())));
})
.toList();

List<Map<LangName, String>> foodLangs = Arrays.stream(foodFields)
.map(Utils::getLangFromField)
.toList();

Utils.getStaticFinalFieldsNameAndValue(MobEffects.class, AutoRegistryObject.class)
Utils.getStaticFinalFieldsNameAndValueFrom(MobEffects.class, AutoRegistryObject.class)
.forEach((key, value) -> value.register(MOB_EFFECTS, key.toLowerCase()));

RegisteredItems.addAll(registeredFoods);
Expand All @@ -106,6 +122,16 @@ public NuclearDelight() {

// Register our mod's ForgeConfigSpec so that Forge can create and load the config file for us
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);

foodLangs.stream().map(Map::entrySet).forEach(entries -> entries.stream().map(Map.Entry::getKey).forEach(langName -> {
if (!LangKeyValuePairs.containsKey(langName.getValue()))
LangKeyValuePairs.put(langName.getValue(), new HashMap<>());
}));

for (int i = 0; i < registeredFoods.size(); i++) {
int finalI = i;
foodLangs.get(i).forEach((key, value) -> LangKeyValuePairs.get(key.getValue()).put(() -> registeredFoods.get(finalI).get().getDescriptionId(), value));
}
}

private void commonSetup(final FMLCommonSetupEvent event) {
Expand Down
56 changes: 43 additions & 13 deletions src/main/java/com/gensokyo/nucleardelight/Utils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.gensokyo.nucleardelight;

import com.gensokyo.nucleardelight.datagenerator.LangName;
import com.gensokyo.nucleardelight.datagenerator.Langs;
import com.mojang.logging.LogUtils;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
Expand All @@ -11,31 +13,59 @@
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class Utils {
private static final Logger LOGGER = LogUtils.getLogger();

public static <T> Map<String, T> getStaticFinalFieldsNameAndValue(Class<?> clazz, Class<T> valueType) {
public static Field[] getStaticFinalFields(Class<?> clazz, Class<?> valueType) {
Field[] fields = clazz.getDeclaredFields();
return Stream.of(fields).filter(field -> {
int modifiers = field.getModifiers();
return Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && field.getType() == valueType;
}).toList().toArray(new Field[0]);
}

public static <T> Map<String, T> getStaticFinalFieldsNameAndValueFrom(Class<?> clazz, Class<T> valueType) {
Map<String, T> staticFinalFieldsNameAndValue = new HashMap<>();
try {
Field[] fields = clazz.getDeclaredFields();
Field[] fields = getStaticFinalFields(clazz, valueType);
for (Field field : fields) {
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && field.getType() == valueType) {
boolean accessible = field.canAccess(null);
field.setAccessible(true);
T value = (T) field.get(null);
field.setAccessible(accessible);

staticFinalFieldsNameAndValue.put(field.getName(), value);
}
field.setAccessible(true);
staticFinalFieldsNameAndValue.put(field.getName(), (T) field.get(null));
}
} catch (IllegalAccessException e) {
LOGGER.error("Failed to access field", e);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOGGER.error("Failed to get field", e);
}
return staticFinalFieldsNameAndValue;
}

public static <T> Map.Entry<String, T> getNameAndValueFromField(Field field) {
try {
field.setAccessible(true);
return Map.entry(field.getName(), (T) field.get(null));
} catch (IllegalArgumentException | IllegalAccessException e) {
LOGGER.error("Failed to get field", e);
return null;
}
}

public static <T> List<Map.Entry<String, T>> getNameAndValueFromFields(Field[] fields) {
return Stream.of(fields).map(Utils::getNameAndValueFromField).map(entry -> (Map.Entry<String, T>) entry).toList();
}

public static Map<LangName, String> getLangFromField(Field field) {
Langs langs = field.getAnnotation(Langs.class);
if (langs == null) {
return Map.of();
}
Map<LangName, String> langNameAndName = new HashMap<>();
for (int i = 0; i < langs.value().length; i++) {
langNameAndName.put(langs.value()[i].lang(), langs.value()[i].name());
}
return langNameAndName;
}

public static <T> List<RegistryObject<T>> registryObjects(DeferredRegister<T> register, Map<String, Supplier<T>> idAndObjectPairs) {
return idAndObjectPairs.entrySet().stream().map(entry -> register.register(entry.getKey(), entry.getValue())).toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ public static void dataGen(GatherDataEvent event) {

List<Item> items = NuclearDelight.RegisteredItems.stream().map(RegistryObject::get).toList();
event.getGenerator().addProvider(true, new SingleTextureItemModelGenerator(items, packOutput, existingFileHelper));

NuclearDelight.LangKeyValuePairs.forEach((lang, name) -> event.getGenerator().addProvider(true, new LangGenerator(packOutput, lang)));
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/gensokyo/nucleardelight/datagenerator/Lang.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gensokyo.nucleardelight.datagenerator;

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Langs.class)
public @interface Lang {
LangName lang();
String name();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gensokyo.nucleardelight.datagenerator;

import com.gensokyo.nucleardelight.NuclearDelight;
import net.minecraft.data.PackOutput;
import net.minecraftforge.common.data.LanguageProvider;

public class LangGenerator extends LanguageProvider {
public LangGenerator(PackOutput output, String locale) {
super(output, NuclearDelight.MODID, locale);
this.locale = locale;
}

private final String locale;

@Override
protected void addTranslations() {
NuclearDelight.LangKeyValuePairs.get(locale).forEach((key, value) -> add(key.get(), value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gensokyo.nucleardelight.datagenerator;

public enum LangName {
EN_US("en_us"),
ZH_CN("zh_cn");

private final String value;

LangName(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/gensokyo/nucleardelight/datagenerator/Langs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gensokyo.nucleardelight.datagenerator;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Langs {
Lang[] value();
}
16 changes: 16 additions & 0 deletions src/main/java/com/gensokyo/nucleardelight/world/food/Foods.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.gensokyo.nucleardelight.world.food;

import com.gensokyo.nucleardelight.datagenerator.Lang;
import com.gensokyo.nucleardelight.datagenerator.LangName;
import com.gensokyo.nucleardelight.datagenerator.Langs;
import com.gensokyo.nucleardelight.world.effect.MobEffects;
import com.mojang.logging.LogUtils;
import net.minecraft.world.effect.MobEffectInstance;
Expand All @@ -9,8 +12,21 @@
public class Foods {
private static final Logger LOGGER = LogUtils.getLogger();

@Langs({
@Lang(lang = LangName.EN_US, name = "Apple Jam Jar"),
@Lang(lang = LangName.ZH_CN, name = "苹果果酱罐")
})
public static final FoodProperties APPLE_JAM_JAR = new FoodProperties.Builder().alwaysEat()
.effect(() -> new MobEffectInstance(MobEffects.VOMITING.get(), 1000, 1), 1.0F)
.nutrition(1)
.saturationMod(2f).build();

@Langs({
@Lang(lang = LangName.EN_US, name = "Creeper Jam Jar"),
@Lang(lang = LangName.ZH_CN, name = "苦力怕果酱罐")
})
public static final FoodProperties CREEPER_JAM_JAR = new FoodProperties.Builder().alwaysEat()
.effect(() -> new MobEffectInstance(MobEffects.VOMITING.get(), 1000, 1), 1.0F)
.nutrition(1)
.saturationMod(2f).build();
}

0 comments on commit f74bf29

Please sign in to comment.