From 5455cc051a4fe4958c3ad95e65cdc7c0442d6cf5 Mon Sep 17 00:00:00 2001 From: LatvianModder Date: Wed, 3 Jul 2024 15:48:11 +0300 Subject: [PATCH] Changed unique recipe ID system --- .../mods/kubejs/BuiltinKubeJSPlugin.java | 2 + .../recipe/component/BlockComponent.java | 5 ++ .../recipe/component/BlockStateComponent.java | 5 ++ ...ponent.java => EitherRecipeComponent.java} | 16 +++++- .../recipe/component/EnumComponent.java | 13 ++++- .../component/FluidIngredientComponent.java | 9 ++-- .../recipe/component/FluidStackComponent.java | 9 ++-- .../recipe/component/IngredientComponent.java | 19 ++++--- .../recipe/component/ItemStackComponent.java | 9 ++-- .../recipe/component/ListRecipeComponent.java | 26 +++------ .../recipe/component/MapRecipeComponent.java | 17 ++++++ ...omponent.java => PairRecipeComponent.java} | 11 +++- .../recipe/component/RecipeComponent.java | 17 +++--- .../component/RecipeComponentBuilder.java | 18 +++++++ .../component/RecipeComponentWithParent.java | 5 ++ .../recipe/component/RegistryComponent.java | 9 ++++ .../SizedFluidIngredientComponent.java | 13 +++-- .../component/SizedIngredientComponent.java | 19 ++++--- .../recipe/component/TagKeyComponent.java | 5 ++ .../recipe/component/TimeComponent.java | 5 ++ .../recipe/component/UniqueIdBuilder.java | 53 +++++++++++++++++++ .../kubejs/recipe/schema/RecipeSchema.java | 46 ++++++++++------ .../kubejs/recipe_schemas/smithing_trim.json | 2 +- 23 files changed, 250 insertions(+), 83 deletions(-) rename src/main/java/dev/latvian/mods/kubejs/recipe/component/{OrRecipeComponent.java => EitherRecipeComponent.java} (83%) rename src/main/java/dev/latvian/mods/kubejs/recipe/component/{AndRecipeComponent.java => PairRecipeComponent.java} (61%) create mode 100644 src/main/java/dev/latvian/mods/kubejs/recipe/component/UniqueIdBuilder.java diff --git a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java index 512c2d3f1..b943e4214 100644 --- a/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java +++ b/src/main/java/dev/latvian/mods/kubejs/BuiltinKubeJSPlugin.java @@ -92,6 +92,7 @@ import dev.latvian.mods.kubejs.recipe.component.BlockStateComponent; import dev.latvian.mods.kubejs.recipe.component.BooleanComponent; import dev.latvian.mods.kubejs.recipe.component.CharacterComponent; +import dev.latvian.mods.kubejs.recipe.component.EitherRecipeComponent; import dev.latvian.mods.kubejs.recipe.component.EnumComponent; import dev.latvian.mods.kubejs.recipe.component.FluidIngredientComponent; import dev.latvian.mods.kubejs.recipe.component.FluidStackComponent; @@ -608,6 +609,7 @@ public void registerRecipeComponents(RecipeComponentFactoryRegistry registry) { registry.register("enum", EnumComponent.FACTORY); registry.register("map", MapRecipeComponent.FACTORY); registry.register("pattern", MapRecipeComponent.PATTERN_FACTORY); + registry.register("either", EitherRecipeComponent.FACTORY); } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java index c007d0f6c..a3e1d4ea9 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockComponent.java @@ -51,6 +51,11 @@ public String checkEmpty(RecipeKey key, Block value) { return ""; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, Block value) { + builder.append(value.kjs$getIdLocation()); + } + @Override public String toString() { return "block"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java index 9b1b6029c..3a552fb17 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/BlockStateComponent.java @@ -68,6 +68,11 @@ public String checkEmpty(RecipeKey key, BlockState value) { return ""; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, BlockState value) { + builder.append(value.kjs$getIdLocation()); + } + @Override public String toString() { return preferObjectForm ? "block_state" : "block_state_string"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/OrRecipeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/EitherRecipeComponent.java similarity index 83% rename from src/main/java/dev/latvian/mods/kubejs/recipe/component/OrRecipeComponent.java rename to src/main/java/dev/latvian/mods/kubejs/recipe/component/EitherRecipeComponent.java index 512732c29..c01505471 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/OrRecipeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/EitherRecipeComponent.java @@ -5,12 +5,15 @@ import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeExceptionJS; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; +import dev.latvian.mods.kubejs.recipe.schema.RecipeComponentFactory; import dev.latvian.mods.kubejs.script.ConsoleJS; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; @SuppressWarnings("OptionalIsPresent") -public record OrRecipeComponent(RecipeComponent high, RecipeComponent low) implements RecipeComponent> { +public record EitherRecipeComponent(RecipeComponent high, RecipeComponent low) implements RecipeComponent> { + public static final RecipeComponentFactory FACTORY = RecipeComponentFactory.readTwoComponents(EitherRecipeComponent::new); + @Override public Codec> codec() { return Codec.either(high.codec(), low.codec()); @@ -81,6 +84,17 @@ public boolean checkValueHasChanged(Either oldValue, Either newValue return oldValue != newValue; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, Either value) { + var left = value.left(); + + if (left.isPresent()) { + high.buildUniqueId(builder, left.get()); + } else { + low.buildUniqueId(builder, value.right().get()); + } + } + @Override public String toString() { return "either<" + high + ", " + low + ">"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/EnumComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/EnumComponent.java index d8b96b1e0..146d62743 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/EnumComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/EnumComponent.java @@ -33,7 +33,7 @@ public record EnumComponent & StringRepresentable>(EnumTypeInf for (var c : enumTypeInfo.enumConstants()) { if (c instanceof RemappedEnumConstant r && r.getRemappedEnumConstantName().equalsIgnoreCase(s)) { return c; - } else if (c instanceof Enum e && e.name().equalsIgnoreCase(s)) { + } else if (c instanceof Enum e && e.name().equalsIgnoreCase(s)) { return c; } } @@ -55,6 +55,17 @@ public TypeInfo typeInfo() { return enumTypeInfo; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, T value) { + if (value instanceof RemappedEnumConstant r) { + builder.append(r.getRemappedEnumConstantName()); + } else if (value instanceof Enum e) { + builder.append(e.name()); + } else { + builder.append(value.toString()); + } + } + @Override public String toString() { return "enum<" + enumTypeInfo.asClass().getName() + ">"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidIngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidIngredientComponent.java index d7513d19f..62d1dc2cd 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidIngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidIngredientComponent.java @@ -6,14 +6,12 @@ import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.FluidMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.crafting.FluidIngredient; import net.neoforged.neoforge.fluids.crafting.SizedFluidIngredient; -import org.jetbrains.annotations.Nullable; public class FluidIngredientComponent implements RecipeComponent { public static final FluidIngredientComponent FLUID_INGREDIENT = new FluidIngredientComponent(); @@ -48,9 +46,10 @@ public String checkEmpty(RecipeKey key, FluidIngredient value) } @Override - @Nullable - public String createUniqueId(FluidIngredient value) { - return value == null || value.isEmpty() || value.hasNoFluids() ? null : RecipeSchema.normalizeId(value.getStacks()[0].getFluid().kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, FluidIngredient value) { + if (!value.isEmpty()) { + builder.append(value.getStacks()[0].getFluid().kjs$getIdLocation()); + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidStackComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidStackComponent.java index 426f0b495..48dd81c34 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidStackComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/FluidStackComponent.java @@ -6,14 +6,12 @@ import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.FluidMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.crafting.FluidIngredient; import net.neoforged.neoforge.fluids.crafting.SizedFluidIngredient; -import org.jetbrains.annotations.Nullable; public class FluidStackComponent implements RecipeComponent { public static final FluidStackComponent FLUID_STACK = new FluidStackComponent(); @@ -48,9 +46,10 @@ public String checkEmpty(RecipeKey key, FluidStack value) { } @Override - @Nullable - public String createUniqueId(FluidStack value) { - return value == null || value.isEmpty() ? null : RecipeSchema.normalizeId(value.getFluid().kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, FluidStack value) { + if (!value.isEmpty()) { + builder.append(value.getFluid().kjs$getIdLocation()); + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java index e81987f3d..d55133ee7 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/IngredientComponent.java @@ -1,18 +1,17 @@ package dev.latvian.mods.kubejs.recipe.component; import com.mojang.serialization.Codec; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.kubejs.util.TinyMap; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.item.crafting.Ingredient; import net.neoforged.neoforge.common.crafting.SizedIngredient; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -91,10 +90,18 @@ public RecipeComponent> asPatternKey() { } @Override - @Nullable - public String createUniqueId(Ingredient value) { - var item = value == null ? null : value.kjs$getFirst(); - return item == null || item.isEmpty() ? null : RecipeSchema.normalizeId(item.kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, Ingredient value) { + var tag = IngredientWrapper.tagKeyOf(value); + + if (tag != null) { + builder.append(tag.location()); + } else { + var first = value.kjs$getFirst(); + + if (!first.isEmpty()) { + builder.append(first.kjs$getIdLocation()); + } + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java index 82afc2604..a309ea2ac 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ItemStackComponent.java @@ -6,11 +6,9 @@ import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.Nullable; public class ItemStackComponent implements RecipeComponent { public static final ItemStackComponent ITEM_STACK = new ItemStackComponent("item_stack", ItemStack.OPTIONAL_CODEC); @@ -54,9 +52,10 @@ public String checkEmpty(RecipeKey key, ItemStack value) { } @Override - @Nullable - public String createUniqueId(ItemStack value) { - return value == null || value.isEmpty() ? null : RecipeSchema.normalizeId(value.kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, ItemStack value) { + if (!value.isEmpty()) { + builder.append(value.kjs$getIdLocation()); + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ListRecipeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ListRecipeComponent.java index 596ce5212..285959242 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/ListRecipeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/ListRecipeComponent.java @@ -7,7 +7,6 @@ import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Array; import java.util.ArrayList; @@ -130,27 +129,14 @@ public List replace(Context cx, KubeRecipe recipe, List original, Replacem } @Override - @Nullable - public String createUniqueId(List value) { - if (value == null || value.isEmpty()) { - return null; - } - - var sb = new StringBuilder(); - - for (var item : value) { - var u = component.createUniqueId(item); - - if (u != null) { - if (!sb.isEmpty()) { - sb.append('_'); - } - - sb.append(u); + public void buildUniqueId(UniqueIdBuilder builder, List value) { + for (int i = 0; i < value.size(); i++) { + if (i > 0) { + builder.appendSeparator(); } - } - return sb.isEmpty() ? null : sb.toString(); + component.buildUniqueId(builder, value.get(i)); + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/MapRecipeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/MapRecipeComponent.java index 72eec22a1..96093eb10 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/MapRecipeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/MapRecipeComponent.java @@ -113,6 +113,23 @@ public TinyMap replace(Context cx, KubeRecipe recipe, TinyMap origin return map; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, TinyMap value) { + boolean first = true; + + for (var entry : value.entries()) { + if (entry.value() != null) { + if (first) { + first = false; + } else { + builder.appendSeparator(); + } + + component.buildUniqueId(builder, entry.value()); + } + } + } + @Override public String toString() { if (patternKey) { diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/AndRecipeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/PairRecipeComponent.java similarity index 61% rename from src/main/java/dev/latvian/mods/kubejs/recipe/component/AndRecipeComponent.java rename to src/main/java/dev/latvian/mods/kubejs/recipe/component/PairRecipeComponent.java index b4099f296..d17e67fd5 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/AndRecipeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/PairRecipeComponent.java @@ -8,8 +8,8 @@ import java.util.List; -public record AndRecipeComponent(RecipeComponent a, RecipeComponent b, Codec> codec) implements RecipeComponent> { - public AndRecipeComponent(RecipeComponent a, RecipeComponent b) { +public record PairRecipeComponent(RecipeComponent a, RecipeComponent b, Codec> codec) implements RecipeComponent> { + public PairRecipeComponent(RecipeComponent a, RecipeComponent b) { this(a, b, Codec.pair(a.codec(), b.codec())); } @@ -23,6 +23,13 @@ public TypeInfo typeInfo() { return new JSFixedArrayTypeInfo(List.of(new JSOptionalParam("", a.typeInfo()), new JSOptionalParam("", b.typeInfo()))); } + @Override + public void buildUniqueId(UniqueIdBuilder builder, Pair value) { + a.buildUniqueId(builder, value.getFirst()); + builder.appendSeparator(); + b.buildUniqueId(builder, value.getSecond()); + } + @Override public String toString() { return "pair<" + a + ", " + b + ">"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponent.java index 7970d383c..ef4b4c5fd 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponent.java @@ -31,7 +31,7 @@ * * @param The value type of this component * @see RecipeComponentWithParent - * @see AndRecipeComponent + * @see PairRecipeComponent */ @Nullable public interface RecipeComponent { @@ -159,7 +159,7 @@ default void readFromJson(KubeRecipe recipe, RecipeComponentValue cv, JsonObj /** * Declares whether this component should take priority when being - * considered by e.g. an {@link OrRecipeComponent} during deserialization. + * considered by e.g. an {@link EitherRecipeComponent} during deserialization. * * @param recipe The recipe object used for context * @param from The object to be deserialized from @@ -200,9 +200,8 @@ default boolean checkValueHasChanged(T oldValue, T newValue) { return oldValue != newValue; } - @Nullable - default String createUniqueId(T value) { - return value == null ? null : value.toString().toLowerCase().replaceAll("\\W", "_").replaceAll("_{2,}", "_"); + default void buildUniqueId(UniqueIdBuilder builder, T value) { + builder.append(value.toString()); } default RecipeComponent> asList() { @@ -225,12 +224,12 @@ default RecipeComponent> asPatternKey() { return new MapRecipeComponent<>(CharacterComponent.CHARACTER, this, true); } - default OrRecipeComponent or(RecipeComponent other) { - return new OrRecipeComponent<>(this, other); + default EitherRecipeComponent or(RecipeComponent other) { + return new EitherRecipeComponent<>(this, other); } - default AndRecipeComponent and(RecipeComponent other) { - return new AndRecipeComponent<>(this, other); + default PairRecipeComponent and(RecipeComponent other) { + return new PairRecipeComponent<>(this, other); } default RecipeComponent withCodec(Codec codec) { diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentBuilder.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentBuilder.java index 1df35c9ef..7acc41c62 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentBuilder.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentBuilder.java @@ -8,6 +8,7 @@ import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; +import dev.latvian.mods.kubejs.util.Cast; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.JSObjectTypeInfo; import dev.latvian.mods.rhino.type.JSOptionalParam; @@ -147,6 +148,23 @@ public RecipeComponentBuilderMap replace(Context cx, KubeRecipe recipe, RecipeCo return original; } + @Override + public void buildUniqueId(UniqueIdBuilder builder, RecipeComponentBuilderMap value) { + boolean first = true; + + for (var entry : value.entrySet()) { + if (entry.getValue() != null) { + if (first) { + first = false; + } else { + builder.appendSeparator(); + } + + entry.getKey().component.buildUniqueId(builder, Cast.to(entry.getValue())); + } + } + } + @Override public String toString() { return keys.stream().map(RecipeKey::toString).collect(Collectors.joining(", ", "builder<", ">")); diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentWithParent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentWithParent.java index abcbad231..b45acff05 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentWithParent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RecipeComponentWithParent.java @@ -52,4 +52,9 @@ default T replace(Context cx, KubeRecipe recipe, T original, ReplacementMatchInf default String checkEmpty(RecipeKey key, T value) { return parentComponent().checkEmpty(key, value); } + + @Override + default void buildUniqueId(UniqueIdBuilder builder, T value) { + parentComponent().buildUniqueId(builder, value); + } } diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java index ca2bee7e8..935671452 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/RegistryComponent.java @@ -77,6 +77,15 @@ public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) { return (regType != null && regType.baseClass().isInstance(from)) || (from instanceof CharSequence && ID.mc(from.toString()) != null) || (from instanceof JsonPrimitive json && json.isString() && ID.mc(json.getAsString()) != null); } + @Override + public void buildUniqueId(UniqueIdBuilder builder, T value) { + var id = registry.getId(value); + + if (id != null) { + builder.append(id); + } + } + @Override public String toString() { return "registry_element<" + registry + ">"; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedFluidIngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedFluidIngredientComponent.java index 3019cfed9..21819a5bc 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedFluidIngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedFluidIngredientComponent.java @@ -6,14 +6,12 @@ import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.FluidMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.crafting.FluidIngredient; import net.neoforged.neoforge.fluids.crafting.SizedFluidIngredient; -import org.jetbrains.annotations.Nullable; public class SizedFluidIngredientComponent implements RecipeComponent { public static final SizedFluidIngredientComponent FLAT = new SizedFluidIngredientComponent("flat_sized_fluid_ingredient", SizedFluidIngredient.FLAT_CODEC); @@ -57,9 +55,14 @@ public String checkEmpty(RecipeKey key, SizedFluidIngredie } @Override - @Nullable - public String createUniqueId(SizedFluidIngredient value) { - return value == null || value.ingredient().isEmpty() || value.ingredient().hasNoFluids() ? null : RecipeSchema.normalizeId(value.ingredient().getStacks()[0].getFluid().kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, SizedFluidIngredient value) { + if (!value.ingredient().isEmpty()) { + var stacks = value.ingredient().getStacks(); + + if (stacks.length > 0) { + builder.append(stacks[0].getFluid().kjs$getIdLocation()); + } + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java index 59f69fada..49689eb77 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/SizedIngredientComponent.java @@ -1,17 +1,16 @@ package dev.latvian.mods.kubejs.recipe.component; import com.mojang.serialization.Codec; +import dev.latvian.mods.kubejs.bindings.IngredientWrapper; import dev.latvian.mods.kubejs.bindings.SizedIngredientWrapper; import dev.latvian.mods.kubejs.item.ingredient.IngredientJS; import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.match.ItemMatch; import dev.latvian.mods.kubejs.recipe.match.ReplacementMatchInfo; -import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; import dev.latvian.mods.rhino.Context; import dev.latvian.mods.rhino.type.TypeInfo; import net.neoforged.neoforge.common.crafting.SizedIngredient; -import org.jetbrains.annotations.Nullable; public class SizedIngredientComponent implements RecipeComponent { public static final SizedIngredientComponent FLAT = new SizedIngredientComponent("flat_sized_ingredient", SizedIngredient.FLAT_CODEC); @@ -55,10 +54,18 @@ public String checkEmpty(RecipeKey key, SizedIngredient value) } @Override - @Nullable - public String createUniqueId(SizedIngredient value) { - var item = value == null ? null : value.ingredient().kjs$getFirst(); - return item == null || item.isEmpty() ? null : RecipeSchema.normalizeId(item.kjs$getId()).replace('/', '_'); + public void buildUniqueId(UniqueIdBuilder builder, SizedIngredient value) { + var tag = IngredientWrapper.tagKeyOf(value.ingredient()); + + if (tag != null) { + builder.append(tag.location()); + } else { + var first = value.ingredient().kjs$getFirst(); + + if (!first.isEmpty()) { + builder.append(first.kjs$getIdLocation()); + } + } } @Override diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/TagKeyComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/TagKeyComponent.java index 118fca41f..2ddf62ed9 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/TagKeyComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/TagKeyComponent.java @@ -68,6 +68,11 @@ public boolean hasPriority(Context cx, KubeRecipe recipe, Object from) { return from instanceof TagKey || (from instanceof CharSequence && from.toString().startsWith("#")) || (from instanceof JsonPrimitive json && json.isString() && json.getAsString().startsWith("#")); } + @Override + public void buildUniqueId(UniqueIdBuilder builder, TagKey value) { + builder.append(value.location()); + } + @Override public String toString() { var key = (ResourceKey) registry; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/TimeComponent.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/TimeComponent.java index 83a895554..568253caa 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/component/TimeComponent.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/TimeComponent.java @@ -38,6 +38,11 @@ public TickDuration wrap(Context cx, KubeRecipe recipe, Object from) { } } + @Override + public void buildUniqueId(UniqueIdBuilder builder, TickDuration value) { + builder.append(value.ticks() + "t"); + } + @Override public String toString() { return name; diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/component/UniqueIdBuilder.java b/src/main/java/dev/latvian/mods/kubejs/recipe/component/UniqueIdBuilder.java new file mode 100644 index 000000000..dcd81da4d --- /dev/null +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/component/UniqueIdBuilder.java @@ -0,0 +1,53 @@ +package dev.latvian.mods.kubejs.recipe.component; + +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.util.regex.Pattern; + +public record UniqueIdBuilder(StringBuilder builder) { + public static final Pattern NON_W_PATTERN = Pattern.compile("\\W"); + public static final Pattern MULTIPLE_UNDERSCORES_PATTERN = Pattern.compile("_{2,}"); + + public void appendSeparator() { + builder.append('_'); + } + + public void append(@Nullable String string) { + if (string != null && !string.isEmpty()) { + builder.append('_'); + builder.append(string); + } + } + + public void append(@Nullable ResourceLocation id) { + if (id == null) { + return; + } + + builder.append('_'); + + if (!id.getNamespace().equals("minecraft") && !id.getNamespace().equals("kubejs")) { + builder.append(id.getNamespace()); + builder.append('_'); + } + + builder.append(id.getPath()); + } + + public String build() { + var result = builder.toString(); + builder.setLength(0); + result = MULTIPLE_UNDERSCORES_PATTERN.matcher(NON_W_PATTERN.matcher(result.toLowerCase()).replaceAll("_")).replaceAll("_"); + + if (!result.isEmpty() && result.charAt(0) == '_') { + result = result.substring(1); + } + + if (!result.isEmpty() && result.charAt(result.length() - 1) == '_') { + result = result.substring(0, result.length() - 1); + } + + return result.isEmpty() ? null : result; + } +} diff --git a/src/main/java/dev/latvian/mods/kubejs/recipe/schema/RecipeSchema.java b/src/main/java/dev/latvian/mods/kubejs/recipe/schema/RecipeSchema.java index a361700c1..a6ab23c83 100644 --- a/src/main/java/dev/latvian/mods/kubejs/recipe/schema/RecipeSchema.java +++ b/src/main/java/dev/latvian/mods/kubejs/recipe/schema/RecipeSchema.java @@ -6,6 +6,7 @@ import dev.latvian.mods.kubejs.recipe.KubeRecipe; import dev.latvian.mods.kubejs.recipe.RecipeKey; import dev.latvian.mods.kubejs.recipe.RecipeTypeFunction; +import dev.latvian.mods.kubejs.recipe.component.UniqueIdBuilder; import dev.latvian.mods.kubejs.util.Cast; import dev.latvian.mods.kubejs.util.JsonUtils; import dev.latvian.mods.rhino.util.RemapForJS; @@ -133,24 +134,45 @@ public RecipeSchema uniqueId(Function uniqueIdFunction) { public RecipeSchema uniqueId(RecipeKey key) { return uniqueId(r -> { var value = r.getValue(key); - return value == null ? null : key.component.createUniqueId(Cast.to(value)); + + if (value != null) { + var builder = new UniqueIdBuilder(new StringBuilder()); + key.component.buildUniqueId(builder, Cast.to(value)); + return builder.build(); + } + + return null; }); } public RecipeSchema uniqueIds(SequencedCollection> keys) { + if (keys.isEmpty()) { + return uniqueId(DEFAULT_UNIQUE_ID_FUNCTION); + } else if (keys.size() == 1) { + return uniqueId(keys.getFirst()); + } + return uniqueId(r -> { var sb = new StringBuilder(); + var builder = new UniqueIdBuilder(new StringBuilder()); + boolean first = true; for (var key : keys) { var value = r.getValue(key); - var u = value == null ? null : key.component.createUniqueId(Cast.to(value)); - if (u != null) { - if (!sb.isEmpty()) { - sb.append('_'); - } + if (value != null) { + key.component.buildUniqueId(builder, Cast.to(value)); + var result = builder.build(); - sb.append(u); + if (result != null) { + if (first) { + first = false; + } else { + sb.append('/'); + } + + sb.append(result); + } } } @@ -158,16 +180,6 @@ public RecipeSchema uniqueIds(SequencedCollection> keys) { }); } - public static String normalizeId(String id) { - if (id.startsWith("minecraft:")) { - return id.substring(10); - } else if (id.startsWith("kubejs:")) { - return id.substring(7); - } else { - return id; - } - } - public Int2ObjectMap constructors() { if (constructors == null) { var keys1 = Arrays.stream(keys).filter(RecipeKey::includeInAutoConstructors).toArray(RecipeKey[]::new); diff --git a/src/main/resources/data/minecraft/kubejs/recipe_schemas/smithing_trim.json b/src/main/resources/data/minecraft/kubejs/recipe_schemas/smithing_trim.json index 8c14f7723..5bb6ff568 100644 --- a/src/main/resources/data/minecraft/kubejs/recipe_schemas/smithing_trim.json +++ b/src/main/resources/data/minecraft/kubejs/recipe_schemas/smithing_trim.json @@ -16,5 +16,5 @@ "type": "ingredient" } ], - "unique": ["base"] + "unique": ["template", "base"] } \ No newline at end of file