diff --git a/common/src/main/java/dev/anvilcraft/lib/data/DataProviderType.java b/common/src/main/java/dev/anvilcraft/lib/data/DataProviderType.java index b2645cb..3291cf5 100644 --- a/common/src/main/java/dev/anvilcraft/lib/data/DataProviderType.java +++ b/common/src/main/java/dev/anvilcraft/lib/data/DataProviderType.java @@ -1,10 +1,14 @@ package dev.anvilcraft.lib.data; +import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; -import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.tags.TagsProvider; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.function.Consumer; public interface DataProviderType

{ DataProviderType ITEM_MODEL = new DataProviderType<>() { @@ -12,11 +16,40 @@ public interface DataProviderType

{ DataProviderType BLOCK_MODEL = new DataProviderType<>() { }; DataProviderType RECIPE = new DataProviderType<>() { + @Override + public void create(@NotNull DataGenerator.PackGenerator generator, @NotNull String namespace, @NotNull List> consumer) { + generator.addProvider(output -> { + RegistratorRecipeProvider provider = new RegistratorRecipeProvider(output); + consumer.forEach(c -> c.accept(provider)); + return provider; + }); + } }; DataProviderType> ITEM_TAG = new DataProviderType<>() { }; DataProviderType> BLOCK_TAG = new DataProviderType<>() { }; DataProviderType LANG = new DataProviderType<>() { + @Override + public void create(@NotNull DataGenerator.PackGenerator generator, @NotNull String namespace, @NotNull List> consumer) { + generator.addProvider(output -> { + LanguageProvider provider = new LanguageProvider(output, namespace); + consumer.forEach(c -> c.accept(provider)); + return provider; + }); + generator.addProvider(output -> { + LanguageProvider provider = new UpsideDownLanguageProvider(output, namespace); + consumer.forEach(c -> c.accept(provider)); + return provider; + }); + } }; + + default void create(@NotNull DataGenerator.PackGenerator generator, @NotNull String namespace, @NotNull List> consumer) { + } + + @SuppressWarnings("unchecked") + default void create(@NotNull String namespace, @NotNull DataGenerator.PackGenerator generator, @NotNull List> consumer) { + this.create(generator, namespace, consumer.stream().map(c -> (Consumer

) c).toList()); + } } diff --git a/common/src/main/java/dev/anvilcraft/lib/data/LanguageProvider.java b/common/src/main/java/dev/anvilcraft/lib/data/LanguageProvider.java index a9cb38a..4d6a1e6 100644 --- a/common/src/main/java/dev/anvilcraft/lib/data/LanguageProvider.java +++ b/common/src/main/java/dev/anvilcraft/lib/data/LanguageProvider.java @@ -8,12 +8,16 @@ import org.jetbrains.annotations.NotNull; import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CompletableFuture; -public abstract class LanguageProvider implements DataProvider { +public class LanguageProvider implements DataProvider { protected final String namespace; protected final String languageCode; protected final PackOutput dataOutput; + protected final Map translations = Collections.synchronizedMap(new HashMap<>()); protected LanguageProvider(PackOutput dataOutput, String namespace, String languageCode) { this.namespace = namespace; @@ -21,7 +25,20 @@ protected LanguageProvider(PackOutput dataOutput, String namespace, String langu this.dataOutput = dataOutput; } - public abstract void add(TranslationBuilder builder); + public static @NotNull LanguageProvider create(PackOutput dataOutput, String namespace, @NotNull String languageCode) { + if (languageCode.equals("en_ud")) { + return new UpsideDownLanguageProvider(dataOutput, namespace); + } + return new LanguageProvider(dataOutput, namespace, languageCode); + } + + protected void add(@NotNull TranslationBuilder builder) { + this.translations.forEach(builder::add); + } + + public void add(String translationKey, String value) { + this.translations.put(translationKey, value); + } public LanguageProvider(PackOutput dataOutput, String namespace) { this(dataOutput, namespace, "en_us"); @@ -36,8 +53,8 @@ public LanguageProvider(PackOutput dataOutput, String namespace) { protected @NotNull Path getLangFilePath(String code) { return this.dataOutput - .createPathProvider(PackOutput.Target.RESOURCE_PACK, "lang") - .json(new ResourceLocation(this.namespace, code)); + .createPathProvider(PackOutput.Target.RESOURCE_PACK, "lang") + .json(new ResourceLocation(this.namespace, code)); } @Override diff --git a/common/src/main/java/dev/anvilcraft/lib/data/RegistratorRecipeProvider.java b/common/src/main/java/dev/anvilcraft/lib/data/RegistratorRecipeProvider.java index 572fbaa..5dd8f31 100644 --- a/common/src/main/java/dev/anvilcraft/lib/data/RegistratorRecipeProvider.java +++ b/common/src/main/java/dev/anvilcraft/lib/data/RegistratorRecipeProvider.java @@ -5,10 +5,14 @@ import net.minecraft.data.recipes.RecipeProvider; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.function.Consumer; public class RegistratorRecipeProvider extends RecipeProvider implements Consumer { - Consumer writer; + private final List recipes = Collections.synchronizedList(new ArrayList<>()); + private Consumer writer; public RegistratorRecipeProvider(PackOutput output) { super(output); @@ -17,7 +21,7 @@ public RegistratorRecipeProvider(PackOutput output) { @Override public void accept(FinishedRecipe finishedRecipe) { if (this.writer == null) { - /*TODO log error*/ + this.recipes.add(finishedRecipe); return; } this.writer.accept(finishedRecipe); @@ -26,5 +30,6 @@ public void accept(FinishedRecipe finishedRecipe) { @Override public void buildRecipes(@NotNull Consumer writer) { this.writer = writer; + this.recipes.forEach(writer); } } diff --git a/common/src/main/java/dev/anvilcraft/lib/data/UpsideDownLanguageProvider.java b/common/src/main/java/dev/anvilcraft/lib/data/UpsideDownLanguageProvider.java index 772b35a..92bff89 100644 --- a/common/src/main/java/dev/anvilcraft/lib/data/UpsideDownLanguageProvider.java +++ b/common/src/main/java/dev/anvilcraft/lib/data/UpsideDownLanguageProvider.java @@ -11,11 +11,16 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public abstract class UpsideDownLanguageProvider extends LanguageProvider { +public class UpsideDownLanguageProvider extends LanguageProvider { protected UpsideDownLanguageProvider(PackOutput dataOutput, String namespace) { super(dataOutput, namespace, "en_ud"); } + @Override + public @NotNull String getName() { + return "UpsideDownLanguage"; + } + @Override public @NotNull CompletableFuture run(@NotNull CachedOutput output) { JsonObject object = new JsonObject(); diff --git a/common/src/main/java/dev/anvilcraft/lib/registrator/AbstractRegistrator.java b/common/src/main/java/dev/anvilcraft/lib/registrator/AbstractRegistrator.java index 6ca2701..07844fe 100644 --- a/common/src/main/java/dev/anvilcraft/lib/registrator/AbstractRegistrator.java +++ b/common/src/main/java/dev/anvilcraft/lib/registrator/AbstractRegistrator.java @@ -26,7 +26,7 @@ @SuppressWarnings("unused") public abstract class AbstractRegistrator { protected final BuilderManager manager = new BuilderManager(); - protected final Map, List>> dataProviders = Collections.synchronizedMap(new HashMap<>()); + protected final Map, List>> dataProviders = Collections.synchronizedMap(new HashMap<>()); private final String modid; protected AbstractRegistrator(String modid) { @@ -70,13 +70,12 @@ public

void data(DataProviderType

type, Consumer

public void init() { } - @SuppressWarnings("unchecked") - protected

List> getDataProviders(DataProviderType

type) { - return (List>) (List) this.dataProviders.getOrDefault(type, Collections.emptyList()); - } - @SuppressWarnings("UnusedReturnValue") - public AbstractRegistrator initDatagen(DataGenerator generator) { + public AbstractRegistrator initDatagen(DataGenerator.PackGenerator generator) { + for (Map.Entry, List>> entry : this.dataProviders.entrySet()) { + entry.getKey().create(this.modid, generator, entry.getValue()); + } + return this; } @@ -89,4 +88,8 @@ public AbstractRegistrator addBuilder(Registry registry, EntryBuilder List> getBuilders(Registry registry) { return this.manager.getBuilders(registry); } + + public void lang(String key, String name) { + this.data(DataProviderType.LANG, provider -> provider.add(key, name)); + } } diff --git a/common/src/main/java/dev/anvilcraft/lib/registrator/builder/EntryBuilder.java b/common/src/main/java/dev/anvilcraft/lib/registrator/builder/EntryBuilder.java index 8cfb1fa..391b357 100644 --- a/common/src/main/java/dev/anvilcraft/lib/registrator/builder/EntryBuilder.java +++ b/common/src/main/java/dev/anvilcraft/lib/registrator/builder/EntryBuilder.java @@ -3,6 +3,7 @@ import dev.anvilcraft.lib.registrator.AbstractRegistrator; import dev.anvilcraft.lib.registrator.entry.RegistryEntry; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; public abstract class EntryBuilder { protected final AbstractRegistrator registrator; @@ -21,4 +22,22 @@ protected EntryBuilder(AbstractRegistrator registrator, String id) { public ResourceLocation getId() { return this.registrator.of(this.id); } + + protected static @NotNull String toTitleCase(@NotNull String input) { + // 使用下划线分割字符串 + String[] parts = input.split("_"); + StringBuilder result = new StringBuilder(); + + for (String part : parts) { + // 将每个单词的首字母转为大写,其余字母保持原样 + if (!part.isEmpty()) { + result.append(Character.toUpperCase(part.charAt(0))); + result.append(part.substring(1)); + } + result.append(" "); + } + + // 删除最后一个多余的空格 + return result.toString().trim(); + } } diff --git a/common/src/main/java/dev/anvilcraft/lib/registrator/builder/ItemBuilder.java b/common/src/main/java/dev/anvilcraft/lib/registrator/builder/ItemBuilder.java index 581fc54..5e66bcd 100644 --- a/common/src/main/java/dev/anvilcraft/lib/registrator/builder/ItemBuilder.java +++ b/common/src/main/java/dev/anvilcraft/lib/registrator/builder/ItemBuilder.java @@ -6,6 +6,7 @@ import dev.anvilcraft.lib.mixin.ItemPropertiesAccessor; import dev.anvilcraft.lib.registrator.AbstractRegistrator; import dev.anvilcraft.lib.registrator.entry.ItemEntry; +import net.minecraft.Util; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; @@ -26,6 +27,7 @@ public ItemBuilder(AbstractRegistrator registrator, String id, Function(this); + this.lang(toTitleCase(this.id)); } public ItemBuilder model(BiConsumer, AnvilLibItemModelProvider> consumer) { @@ -48,7 +50,9 @@ public ItemBuilder recipe(BiConsumer, RegistratorRecipeProvider> return this; } + @SuppressWarnings("UnusedReturnValue") public ItemBuilder lang(String name) { + this.registrator.lang(Util.makeDescriptionId("item", this.registrator.of(this.id)), name); return this; } @@ -63,14 +67,14 @@ public ItemBuilder initProperties(Supplier supplier) { if (supplier instanceof ItemEntry itemEntry) { ItemPropertiesAccessor accessor = (ItemPropertiesAccessor) itemEntry.getItemBuilder().properties; if ( - accessor.getMaxStackSize() != defaultProperties.getMaxStackSize() - && thisAccessor.getMaxStackSize() == defaultProperties.getMaxStackSize() + accessor.getMaxStackSize() != defaultProperties.getMaxStackSize() + && thisAccessor.getMaxStackSize() == defaultProperties.getMaxStackSize() ) { this.properties.stacksTo(accessor.getMaxStackSize()); } if ( - accessor.getMaxDamage() != defaultProperties.getMaxDamage() - && thisAccessor.getMaxDamage() == defaultProperties.getMaxDamage() + accessor.getMaxDamage() != defaultProperties.getMaxDamage() + && thisAccessor.getMaxDamage() == defaultProperties.getMaxDamage() ) { this.properties.durability(accessor.getMaxDamage()); } @@ -78,8 +82,8 @@ public ItemBuilder initProperties(Supplier supplier) { this.properties.craftRemainder(accessor.getCraftingRemainingItem()); } if ( - accessor.getRarity() != defaultProperties.getRarity() - && thisAccessor.getRarity() == defaultProperties.getRarity() + accessor.getRarity() != defaultProperties.getRarity() + && thisAccessor.getRarity() == defaultProperties.getRarity() ) { this.properties.rarity(accessor.getRarity()); } @@ -93,8 +97,8 @@ public ItemBuilder initProperties(Supplier supplier) { Item item = supplier.get(); if (item != null) { if ( - item.getMaxDamage() != defaultProperties.getMaxDamage() - && thisAccessor.getMaxDamage() == defaultProperties.getMaxDamage() + item.getMaxDamage() != defaultProperties.getMaxDamage() + && thisAccessor.getMaxDamage() == defaultProperties.getMaxDamage() ) { this.properties.durability(item.getMaxDamage()); } @@ -102,25 +106,25 @@ public ItemBuilder initProperties(Supplier supplier) { this.properties.craftRemainder(item.getCraftingRemainingItem()); } if ( - item.getRarity(new ItemStack(item)) != defaultProperties.getRarity() - && thisAccessor.getRarity() == defaultProperties.getRarity() + item.getRarity(new ItemStack(item)) != defaultProperties.getRarity() + && thisAccessor.getRarity() == defaultProperties.getRarity() ) { this.properties.rarity(item.getRarity(new ItemStack(item))); } if ( - item.getMaxStackSize() != defaultProperties.getMaxStackSize() - && thisAccessor.getMaxStackSize() == defaultProperties.getMaxStackSize() + item.getMaxStackSize() != defaultProperties.getMaxStackSize() + && thisAccessor.getMaxStackSize() == defaultProperties.getMaxStackSize() ) { this.properties.stacksTo(item.getMaxStackSize()); } if ( - item.getFoodProperties() != null - && thisAccessor.getFoodProperties() == null + item.getFoodProperties() != null + && thisAccessor.getFoodProperties() == null ) { this.properties.food(item.getFoodProperties()); } if ( - item.isFireResistant() && !thisAccessor.isFireResistant() + item.isFireResistant() && !thisAccessor.isFireResistant() ) { this.properties.fireResistant(); } diff --git a/fabric/src/test/generated/resources/.cache/2fc0a18b1befa47ffaddca78faee788f5ecfb9cb b/fabric/src/test/generated/resources/.cache/2fc0a18b1befa47ffaddca78faee788f5ecfb9cb new file mode 100644 index 0000000..53487f4 --- /dev/null +++ b/fabric/src/test/generated/resources/.cache/2fc0a18b1befa47ffaddca78faee788f5ecfb9cb @@ -0,0 +1,3 @@ +// 1.20.1 2024-08-31T15:38:52.951909 AnvilLib Test/Recipes +4cd064cbd4fa1437c2a145d2176b2cbb5b7ccc06 data/anvil-lib-test/advancements/recipes/misc/test.json +5ff54d03f1e14bdfe21d703af7ab8622773d680c data/anvil-lib-test/recipes/test.json diff --git a/fabric/src/test/generated/resources/.cache/af8f5f55c1320d7b783487b0749ad66525e7e7eb b/fabric/src/test/generated/resources/.cache/af8f5f55c1320d7b783487b0749ad66525e7e7eb new file mode 100644 index 0000000..1f8497e --- /dev/null +++ b/fabric/src/test/generated/resources/.cache/af8f5f55c1320d7b783487b0749ad66525e7e7eb @@ -0,0 +1,2 @@ +// 1.20.1 2024-08-31T15:38:52.958558 AnvilLib Test/UpsideDownLanguage +4f2270cb5b55f19f5fd5a278fec75b064631cbfa assets/anvil-lib-test/lang/en_ud.json diff --git a/fabric/src/test/generated/resources/.cache/be0358542ac885878a467772a460af89c9bc4d44 b/fabric/src/test/generated/resources/.cache/be0358542ac885878a467772a460af89c9bc4d44 new file mode 100644 index 0000000..dc9eac3 --- /dev/null +++ b/fabric/src/test/generated/resources/.cache/be0358542ac885878a467772a460af89c9bc4d44 @@ -0,0 +1,2 @@ +// 1.20.1 2024-08-31T15:38:52.956432 AnvilLib Test/Language +5cca06a243afdcb758b4e9b0c89bb9a8e102719d assets/anvil-lib-test/lang/en_us.json diff --git a/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_ud.json b/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_ud.json new file mode 100644 index 0000000..6c5dafa --- /dev/null +++ b/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_ud.json @@ -0,0 +1,3 @@ +{ + "item.anvil-lib-test.test": "ʇsǝ⟘" +} \ No newline at end of file diff --git a/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_us.json b/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_us.json new file mode 100644 index 0000000..a5ea16b --- /dev/null +++ b/fabric/src/test/generated/resources/assets/anvil-lib-test/lang/en_us.json @@ -0,0 +1,3 @@ +{ + "item.anvil-lib-test.test": "Test" +} \ No newline at end of file diff --git a/fabric/src/test/generated/resources/data/anvil-lib-test/advancements/recipes/misc/test.json b/fabric/src/test/generated/resources/data/anvil-lib-test/advancements/recipes/misc/test.json new file mode 100644 index 0000000..48d4c43 --- /dev/null +++ b/fabric/src/test/generated/resources/data/anvil-lib-test/advancements/recipes/misc/test.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_apple": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:apple" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvil-lib-test:test" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_apple", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvil-lib-test:test" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/fabric/src/test/generated/resources/data/anvil-lib-test/recipes/test.json b/fabric/src/test/generated/resources/data/anvil-lib-test/recipes/test.json new file mode 100644 index 0000000..d9aef35 --- /dev/null +++ b/fabric/src/test/generated/resources/data/anvil-lib-test/recipes/test.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "x": { + "item": "minecraft:apple" + } + }, + "pattern": [ + "xxx", + "xxx", + "xxx" + ], + "result": { + "item": "anvil-lib-test:test" + }, + "show_notification": true +} \ No newline at end of file diff --git a/fabric/src/test/java/dev/anvilcraft/lib/test/AnvilLibTestDataGenerator.java b/fabric/src/test/java/dev/anvilcraft/lib/test/AnvilLibTestDataGenerator.java index 036d21c..55ab76b 100644 --- a/fabric/src/test/java/dev/anvilcraft/lib/test/AnvilLibTestDataGenerator.java +++ b/fabric/src/test/java/dev/anvilcraft/lib/test/AnvilLibTestDataGenerator.java @@ -2,10 +2,11 @@ import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; +import org.jetbrains.annotations.NotNull; public class AnvilLibTestDataGenerator implements DataGeneratorEntrypoint { @Override - public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { - AnvilLibTest.REGISTRATOR.initDatagen(fabricDataGenerator); + public void onInitializeDataGenerator(@NotNull FabricDataGenerator fabricDataGenerator) { + AnvilLibTest.REGISTRATOR.initDatagen(fabricDataGenerator.createPack()); } } diff --git a/fabric/src/test/java/dev/anvilcraft/lib/test/TestRegisters.java b/fabric/src/test/java/dev/anvilcraft/lib/test/TestRegisters.java index abb6ecb..f5184b8 100644 --- a/fabric/src/test/java/dev/anvilcraft/lib/test/TestRegisters.java +++ b/fabric/src/test/java/dev/anvilcraft/lib/test/TestRegisters.java @@ -5,6 +5,7 @@ import dev.anvilcraft.lib.registrator.entry.TagKeyEntry; import net.minecraft.core.registries.Registries; import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; @@ -27,6 +28,7 @@ public class TestRegisters { .pattern("xxx") .pattern("xxx") .define('x', Items.APPLE) + .unlockedBy("has_apple", RecipeProvider.has(Items.APPLE)) .save(provider)) .register();