From 3361079380c79e3aba7b324680687228c7309944 Mon Sep 17 00:00:00 2001 From: YoungOnion <39562198+YoungOnionMC@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:04:05 -0600 Subject: [PATCH] Fix OutputItems in kubeJS stripping NBT (#1852) Co-authored-by: YoungOnionMC Co-authored-by: screret <68943070+screret@users.noreply.github.com> --- .../integration/kjs/GregTechKubeJSPlugin.java | 41 +++--- .../kjs/recipe/GTRecipeSchema.java | 52 +++++--- .../recipe/components/ExtendedOutputItem.java | 124 ++++++++++++++++++ .../recipe/components/GTRecipeComponents.java | 40 +++--- 4 files changed, 202 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/ExtendedOutputItem.java diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java index bfdb1ad369..d88abb592f 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java @@ -55,6 +55,7 @@ import com.gregtechceu.gtceu.integration.kjs.builders.prefix.OreTagPrefixBuilder; import com.gregtechceu.gtceu.integration.kjs.helpers.MaterialStackWrapper; import com.gregtechceu.gtceu.integration.kjs.recipe.GTRecipeSchema; +import com.gregtechceu.gtceu.integration.kjs.recipe.components.ExtendedOutputItem; import com.gregtechceu.gtceu.integration.kjs.recipe.components.GTRecipeComponents; import net.minecraft.core.registries.BuiltInRegistries; @@ -182,6 +183,7 @@ public void registerRecipeComponents(RecipeComponentFactoryRegistryEvent event) event.register("gtSuOut", GTRecipeComponents.SU_OUT); event.register("gtChance", GTRecipeComponents.CHANCE_LOGIC_MAP); + event.register("extendedOutputItem", GTRecipeComponents.EXTENDED_OUTPUT); event.register("fluidIngredient", GTRecipeComponents.FLUID_INGREDIENT); event.register("fluidIngredientOut", GTRecipeComponents.FLUID_INGREDIENT_OUT); @@ -249,7 +251,7 @@ public void registerBindings(BindingsEvent event) { @Override public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) { super.registerTypeWrappers(type, typeWrappers); - typeWrappers.register(GTRecipeType.class, (ctx, o) -> { + typeWrappers.registerSimple(GTRecipeType.class, o -> { if (o instanceof Wrapper w) { o = w.unwrap(); } @@ -258,28 +260,28 @@ public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) { return null; }); - typeWrappers.register(Element.class, (ctx, o) -> { + typeWrappers.registerSimple(Element.class, o -> { if (o instanceof Element element) return element; if (o instanceof CharSequence chars) return GTElements.get(chars.toString()); return null; }); - typeWrappers.register(Material.class, (ctx, o) -> { + typeWrappers.registerSimple(Material.class, o -> { if (o instanceof Material material) return material; if (o instanceof CharSequence chars) return GTMaterials.get(chars.toString()); return null; }); - typeWrappers.register(MachineDefinition.class, (ctx, o) -> { + typeWrappers.registerSimple(MachineDefinition.class, o -> { if (o instanceof MachineDefinition definition) return definition; if (o instanceof CharSequence chars) return GTMachines.get(chars.toString()); return null; }); - typeWrappers.register(TagPrefix.class, (ctx, o) -> { + typeWrappers.registerSimple(TagPrefix.class, o -> { if (o instanceof TagPrefix tagPrefix) return tagPrefix; if (o instanceof CharSequence chars) return TagPrefix.get(chars.toString()); return null; }); - typeWrappers.register(UnificationEntry.class, (ctx, o) -> { + typeWrappers.registerSimple(UnificationEntry.class, o -> { if (o instanceof UnificationEntry entry) return entry; if (o instanceof CharSequence chars) { var values = chars.toString().split(":"); @@ -292,29 +294,30 @@ public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) { } return null; }); - typeWrappers.register(RecipeCapability.class, (ctx, o) -> { + typeWrappers.registerSimple(RecipeCapability.class, o -> { if (o instanceof RecipeCapability capability) return capability; if (o instanceof CharSequence chars) return GTRegistries.RECIPE_CAPABILITIES.get(chars.toString()); return null; }); - typeWrappers.register(ChanceLogic.class, (ctx, o) -> { + typeWrappers.registerSimple(ChanceLogic.class, o -> { if (o instanceof ChanceLogic capability) return capability; if (o instanceof CharSequence chars) return GTRegistries.CHANCE_LOGICS.get(chars.toString()); return null; }); + typeWrappers.registerSimple(ExtendedOutputItem.class, ExtendedOutputItem::of); - typeWrappers.register(MaterialIconSet.class, (ctx, o) -> { + typeWrappers.registerSimple(MaterialIconSet.class, o -> { if (o instanceof MaterialIconSet iconSet) return iconSet; if (o instanceof CharSequence chars) return MaterialIconSet.getByName(chars.toString()); return null; }); - typeWrappers.register(MaterialStack.class, (ctx, o) -> { + typeWrappers.registerSimple(MaterialStack.class, o -> { if (o instanceof MaterialStack stack) return stack; if (o instanceof Material material) return new MaterialStack(material, 1); if (o instanceof CharSequence chars) return MaterialStack.fromString(chars); return null; }); - typeWrappers.register(MaterialStackWrapper.class, (ctx, o) -> { + typeWrappers.registerSimple(MaterialStackWrapper.class, o -> { if (o instanceof MaterialStackWrapper wrapper) return wrapper; if (o instanceof MaterialStack stack) return new MaterialStackWrapper(stack::material, stack.amount()); if (o instanceof Material material) return new MaterialStackWrapper(() -> material, 1); @@ -322,51 +325,51 @@ public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) { return null; }); - typeWrappers.register(IWorldGenLayer.class, (ctx, o) -> { + typeWrappers.registerSimple(IWorldGenLayer.class, o -> { if (o instanceof IWorldGenLayer layer) return layer; if (o instanceof CharSequence chars) return WorldGenLayers.getByName(chars.toString()); return null; }); - typeWrappers.register(HeightRangePlacement.class, (ctx, o) -> { + typeWrappers.registerSimple(HeightRangePlacement.class, o -> { if (o instanceof HeightRangePlacement placement) return placement; return Optional.ofNullable(NBTUtils.toTagCompound(o)) .map(tag -> HeightRangePlacement.CODEC.parse(NbtOps.INSTANCE, tag)) .flatMap(DataResult::result) .orElse(null); }); - typeWrappers.register(BiomeWeightModifier.class, (ctx, o) -> { + typeWrappers.registerSimple(BiomeWeightModifier.class, o -> { if (o instanceof BiomeWeightModifier modifier) return modifier; return Optional.ofNullable(NBTUtils.toTagCompound(o)) .map(tag -> BiomeWeightModifier.CODEC.parse(NbtOps.INSTANCE, tag)) .flatMap(DataResult::result) .orElse(null); }); - typeWrappers.register(VeinGenerator.class, (ctx, o) -> { + typeWrappers.registerSimple(VeinGenerator.class, o -> { if (o instanceof VeinGenerator generator) return generator; return Optional.ofNullable(NBTUtils.toTagCompound(o)) .map(tag -> VeinGenerator.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag)) .flatMap(DataResult::result) .orElse(null); }); - typeWrappers.register(IndicatorGenerator.class, (ctx, o) -> { + typeWrappers.registerSimple(IndicatorGenerator.class, o -> { if (o instanceof IndicatorGenerator generator) return generator; return Optional.ofNullable(NBTUtils.toTagCompound(o)) .map(tag -> IndicatorGenerator.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag)) .flatMap(DataResult::result) .orElse(null); }); - typeWrappers.register(IndicatorPlacement.class, (ctx, o) -> { + typeWrappers.registerSimple(IndicatorPlacement.class, o -> { if (o instanceof IndicatorPlacement placement) return placement; if (o instanceof CharSequence str) return IndicatorPlacement.getByName(str.toString()); return null; }); - typeWrappers.register(MedicalCondition.class, (ctx, o) -> { + typeWrappers.registerSimple(MedicalCondition.class, o -> { if (o instanceof MedicalCondition condition) return condition; if (o instanceof CharSequence str) return MedicalCondition.CONDITIONS.get(str.toString()); return null; }); // jank because Rhino doesn't agree that it's an interface - typeWrappers.register(IWorldGenLayer.RuleTestSupplier.class, (ctx, o) -> { + typeWrappers.registerSimple(IWorldGenLayer.RuleTestSupplier.class, o -> { if (o instanceof IWorldGenLayer.RuleTestSupplier supplier) return supplier; return () -> BlockStatePredicate.ruleTestOf(o); }); diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java index d9bc2f3558..519f2d2e22 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/GTRecipeSchema.java @@ -20,6 +20,7 @@ import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder; import com.gregtechceu.gtceu.integration.kjs.recipe.components.CapabilityMap; +import com.gregtechceu.gtceu.integration.kjs.recipe.components.ExtendedOutputItem; import com.gregtechceu.gtceu.integration.kjs.recipe.components.GTRecipeComponents; import com.gregtechceu.gtceu.utils.ResearchManager; @@ -256,7 +257,7 @@ public GTRecipeJS inputItems(MachineDefinition machine, int count) { return inputItems(machine.asStack(count)); } - public GTRecipeJS itemOutputs(InputItem... outputs) { + public GTRecipeJS itemOutputs(ExtendedOutputItem... outputs) { return outputItems(outputs); } @@ -268,8 +269,8 @@ public GTRecipeJS itemOutput(UnificationEntry unificationEntry, int count) { return outputItems(unificationEntry.tagPrefix, unificationEntry.material, count); } - public GTRecipeJS outputItems(InputItem... outputs) { - for (InputItem itemStack : outputs) { + public GTRecipeJS outputItems(ExtendedOutputItem... outputs) { + for (ExtendedOutputItem itemStack : outputs) { if (itemStack.isEmpty()) { GTCEu.LOGGER.error("gt recipe {} output items is empty", id); } @@ -278,11 +279,11 @@ public GTRecipeJS outputItems(InputItem... outputs) { } public GTRecipeJS outputItems(Item input, int amount) { - return outputItems(InputItem.of(new ItemStack(input, amount))); + return outputItems(ExtendedOutputItem.of(new ItemStack(input, amount))); } public GTRecipeJS outputItems(Item input) { - return outputItems(InputItem.of(new ItemStack(input))); + return outputItems(ExtendedOutputItem.of(new ItemStack(input))); } public GTRecipeJS outputItems(TagPrefix orePrefix, Material material) { @@ -290,7 +291,7 @@ public GTRecipeJS outputItems(TagPrefix orePrefix, Material material) { } public GTRecipeJS outputItems(TagPrefix orePrefix, Material material, int count) { - return outputItems(InputItem.of(ChemicalHelper.get(orePrefix, material, count))); + return outputItems(ExtendedOutputItem.of(ChemicalHelper.get(orePrefix, material, count))); } public GTRecipeJS outputItems(MachineDefinition machine) { @@ -298,12 +299,11 @@ public GTRecipeJS outputItems(MachineDefinition machine) { } public GTRecipeJS outputItems(MachineDefinition machine, int count) { - return outputItems(InputItem.of(machine.asStack(count))); + return outputItems(new ExtendedOutputItem(machine.asStack(count))); } - public GTRecipeJS itemOutputsRanged(InputItem ingredient, int min, int max) { - return output(ItemRecipeCapability.CAP, - new IntProviderIngredient(ingredient.ingredient, UniformInt.of(min, max))); + public GTRecipeJS itemOutputsRanged(ExtendedOutputItem ingredient, int min, int max) { + return outputItemsRanged(ingredient.ingredient.getInner(), min, max); } public GTRecipeJS outputItemsRanged(Ingredient ingredient, int min, int max) { @@ -311,12 +311,11 @@ public GTRecipeJS outputItemsRanged(Ingredient ingredient, int min, int max) { } public GTRecipeJS outputItemsRanged(ItemStack stack, int min, int max) { - return output(ItemRecipeCapability.CAP, - new IntProviderIngredient(SizedIngredient.create(stack), UniformInt.of(min, max))); + return outputItemsRanged(Ingredient.of(stack), min, max); } public GTRecipeJS outputItemsRanged(TagPrefix orePrefix, Material material, int min, int max) { - return outputItemsRanged(ChemicalHelper.get(orePrefix, material, 1), min, max); + return outputItemsRanged(ChemicalHelper.get(orePrefix, material), min, max); } public GTRecipeJS notConsumable(InputItem itemStack) { @@ -380,7 +379,7 @@ public GTRecipeJS chancedFluidInput(GTRecipeComponents.FluidIngredientJS stack, return this; } - public GTRecipeJS chancedOutput(InputItem stack, int chance, int tierChanceBoost) { + public GTRecipeJS chancedOutput(ExtendedOutputItem stack, int chance, int tierChanceBoost) { if (0 >= chance || chance > ChanceLogic.getMaxChancedValue()) { GTCEu.LOGGER.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", ChanceLogic.getMaxChancedValue(), chance, new Throwable()); @@ -397,14 +396,14 @@ public GTRecipeJS chancedOutput(InputItem stack, int chance, int tierChanceBoost } public GTRecipeJS chancedOutput(TagPrefix tag, Material mat, int chance, int tierChanceBoost) { - return chancedOutput(InputItem.of(ChemicalHelper.get(tag, mat)), chance, tierChanceBoost); + return chancedOutput(ExtendedOutputItem.of(ChemicalHelper.get(tag, mat)), chance, tierChanceBoost); } public GTRecipeJS chancedOutput(TagPrefix tag, Material mat, int count, int chance, int tierChanceBoost) { - return chancedOutput(InputItem.of(ChemicalHelper.get(tag, mat, count)), chance, tierChanceBoost); + return chancedOutput(ExtendedOutputItem.of(ChemicalHelper.get(tag, mat, count)), chance, tierChanceBoost); } - public GTRecipeJS chancedOutput(InputItem stack, String fraction, int tierChanceBoost) { + public GTRecipeJS chancedOutput(ExtendedOutputItem stack, String fraction, int tierChanceBoost) { if (stack.isEmpty()) { return this; } @@ -472,7 +471,7 @@ public GTRecipeJS chancedOutput(InputItem stack, String fraction, int tierChance public GTRecipeJS chancedOutput(TagPrefix prefix, Material material, int count, String fraction, int tierChanceBoost) { - return chancedOutput(InputItem.of(ChemicalHelper.get(prefix, material, count)), fraction, + return chancedOutput(ExtendedOutputItem.of(ChemicalHelper.get(prefix, material, count)), fraction, tierChanceBoost); } @@ -894,8 +893,17 @@ public JsonElement writeInputItem(InputItem value) { @Override public OutputItem readOutputItem(Object from) { - if (from instanceof SizedIngredient ingredient) { + if (from instanceof ExtendedOutputItem outputItem) { + return outputItem; + } else if (from instanceof OutputItem outputItem) { + return outputItem; + } else if (from instanceof SizedIngredient ingredient) { + if (ingredient.getInner() instanceof IntProviderIngredient intProvider) { + return new ExtendedOutputItem(intProvider, 1); + } return OutputItem.of(ingredient.getInner().getItems()[0], Double.NaN); + } else if (from instanceof IntProviderIngredient ingredient) { + return new ExtendedOutputItem(ingredient, 1); } else if (from instanceof JsonObject jsonObject) { float chance = 1.0f; if (jsonObject.has("chance")) { @@ -912,6 +920,12 @@ public OutputItem readOutputItem(Object from) { @Override public JsonElement writeOutputItem(OutputItem value) { + if (value instanceof ExtendedOutputItem extended) { + if (extended.ingredient.getInner() instanceof IntProviderIngredient intProvider) { + return intProvider.toJson(); + } + return extended.ingredient.toJson(); + } return SizedIngredient.create(value.item).toJson(); } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/ExtendedOutputItem.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/ExtendedOutputItem.java new file mode 100644 index 0000000000..e13da0b3ca --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/ExtendedOutputItem.java @@ -0,0 +1,124 @@ +package com.gregtechceu.gtceu.integration.kjs.recipe.components; + +import com.gregtechceu.gtceu.api.recipe.ingredient.IntProviderIngredient; +import com.gregtechceu.gtceu.api.recipe.ingredient.SizedIngredient; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraftforge.common.crafting.StrictNBTIngredient; + +import com.google.gson.JsonElement; +import dev.latvian.mods.kubejs.item.InputItem; +import dev.latvian.mods.kubejs.item.OutputItem; +import dev.latvian.mods.kubejs.recipe.OutputReplacement; +import dev.latvian.mods.kubejs.recipe.RecipeJS; +import dev.latvian.mods.kubejs.recipe.ReplacementMatch; +import dev.latvian.mods.kubejs.util.ConsoleJS; +import dev.latvian.mods.rhino.NativeObject; + +import java.util.Map; + +public class ExtendedOutputItem extends OutputItem implements OutputReplacement { + + public SizedIngredient ingredient; + + public ExtendedOutputItem(Ingredient ingredient, int count) { + super(ingredient.kjs$getFirst().kjs$withCount(count), Double.NaN, null); + // reset the ingredient if it's an int provider. + if (ingredient instanceof IntProviderIngredient intProvider) { + intProvider.setItemStacks(null); + intProvider.setSampledCount(null); + } + this.ingredient = SizedIngredient.create(ingredient, count); + } + + public ExtendedOutputItem(ItemStack stack) { + super(stack, Double.NaN, null); + this.ingredient = SizedIngredient.create(StrictNBTIngredient.of(stack)); + } + + private ExtendedOutputItem(OutputItem item) { + this(Ingredient.of(item.item), item.getCount()); + } + + public static ExtendedOutputItem of(Object o) { + if (o instanceof ExtendedOutputItem extendedOutput) { + return extendedOutput; + } else if (o instanceof ItemStack stack) { + if (stack.hasTag()) { + return new ExtendedOutputItem(StrictNBTIngredient.of(stack), stack.getCount()); + } else { + return new ExtendedOutputItem(Ingredient.of(stack), stack.getCount()); + } + } else if (o instanceof InputItem input) { + return new ExtendedOutputItem(input.ingredient, input.count); + } else if (o instanceof OutputItem output) { + return ExtendedOutputItem.fromOutputItem(output); + } else if (o instanceof NativeObject nativeObject) { + InputItem input = InputItem.of(nativeObject); + return new ExtendedOutputItem(input.ingredient, input.count); + } else if (o instanceof JsonElement json) { + InputItem input = InputItem.of(json); + return new ExtendedOutputItem(input.ingredient, input.count); + } else if (o instanceof CompoundTag tag) { + InputItem input = InputItem.of(tag); + return new ExtendedOutputItem(input.ingredient, input.count); + } else if (o instanceof Map map) { + InputItem input = InputItem.of(map); + return new ExtendedOutputItem(input.ingredient, input.count); + } + + OutputItem output = OutputItem.of(o); + if (output.item.hasTag()) { + return new ExtendedOutputItem(StrictNBTIngredient.of(output.item), output.getCount()); + } + return new ExtendedOutputItem(output); + } + + public static ExtendedOutputItem fromOutputItem(OutputItem item) { + if (item instanceof ExtendedOutputItem extended) { + return extended; + } + return new ExtendedOutputItem(item); + } + + @Override + public OutputItem withCount(int count) { + ingredient = SizedIngredient.create(ingredient.getInner(), count); + return super.withCount(count); + } + + @Override + public OutputItem withRolls(IntProvider rolls) { + IntProviderIngredient ingredient; + if (this.ingredient.getInner() instanceof IntProviderIngredient intProvider) { + ingredient = new IntProviderIngredient(intProvider.getInner(), rolls); + } else { + ingredient = new IntProviderIngredient(this.ingredient.getInner(), rolls); + } + return new ExtendedOutputItem(ingredient, this.ingredient.getAmount()); + } + + @Override + public int getCount() { + return ingredient.getAmount(); + } + + @Override + public Object replaceOutput(RecipeJS recipe, ReplacementMatch match, OutputReplacement original) { + if (original instanceof ExtendedOutputItem o) { + return new ExtendedOutputItem(this.ingredient, o.getCount()); + } + return super.replaceOutput(recipe, match, original); + } + + @SuppressWarnings("deprecation") + @Override + public InputItem ignoreNBT() { + var console = ConsoleJS.getCurrent(ConsoleJS.SERVER); + console.warn("You don't need to call .ignoreNBT() anymore, all item ingredients ignore NBT by default!"); + return InputItem.of(ingredient.getInner(), ingredient.getAmount()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/GTRecipeComponents.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/GTRecipeComponents.java index 28b54add35..cb6a3d66bd 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/GTRecipeComponents.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/recipe/components/GTRecipeComponents.java @@ -6,6 +6,7 @@ import com.gregtechceu.gtceu.api.recipe.RecipeCondition; import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic; import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient; +import com.gregtechceu.gtceu.api.recipe.ingredient.IntProviderIngredient; import com.gregtechceu.gtceu.api.registry.GTRegistries; import com.gregtechceu.gtceu.common.data.GTRecipeCapabilities; @@ -25,12 +26,12 @@ import dev.latvian.mods.kubejs.fluid.InputFluid; import dev.latvian.mods.kubejs.fluid.OutputFluid; import dev.latvian.mods.kubejs.item.InputItem; +import dev.latvian.mods.kubejs.item.OutputItem; import dev.latvian.mods.kubejs.recipe.*; import dev.latvian.mods.kubejs.recipe.component.*; import dev.latvian.mods.kubejs.typings.desc.DescriptionContext; import dev.latvian.mods.kubejs.typings.desc.TypeDescJS; import dev.latvian.mods.kubejs.util.ListJS; -import dev.latvian.mods.kubejs.util.TinyMap; import dev.latvian.mods.rhino.mod.util.NBTUtils; import java.util.*; @@ -284,11 +285,11 @@ public FluidIngredientJS read(RecipeJS recipe, Object from) { return FluidIngredientJS.of(from); } }; - public static final RecipeComponent INPUT_ITEM_OUT = new RecipeComponent<>() { + public static final RecipeComponent EXTENDED_OUTPUT = new RecipeComponent<>() { @Override public String componentType() { - return "input_item_out"; + return "extended_output_item"; } @Override @@ -298,7 +299,7 @@ public ComponentRole role() { @Override public Class componentClass() { - return InputItem.class; + return OutputItem.class; } @Override @@ -307,22 +308,32 @@ public boolean hasPriority(RecipeJS recipe, Object from) { } @Override - public JsonElement write(RecipeJS recipe, InputItem value) { - return recipe.writeInputItem(value); + public JsonElement write(RecipeJS recipe, ExtendedOutputItem value) { + return recipe.writeOutputItem(value); } @Override - public InputItem read(RecipeJS recipe, Object from) { - return recipe.readInputItem(from); + public ExtendedOutputItem read(RecipeJS recipe, Object from) { + if (from instanceof IntProviderIngredient intProvider) { + return new ExtendedOutputItem(intProvider, 1); + } + return ExtendedOutputItem.fromOutputItem(recipe.readOutputItem(from)); + } + + @Override + public boolean isOutput(RecipeJS recipe, ExtendedOutputItem value, ReplacementMatch match) { + return match instanceof ItemMatch m && !value.isEmpty() && m.contains(value.ingredient); } @Override - public boolean isOutput(RecipeJS recipe, InputItem value, ReplacementMatch match) { - return match instanceof ItemMatch m && value.validForMatching() && m.contains(value.ingredient); + public ExtendedOutputItem replaceOutput(RecipeJS recipe, ExtendedOutputItem original, ReplacementMatch match, + OutputReplacement with) { + return isOutput(recipe, original, match) ? read(recipe, with.replaceOutput(recipe, match, original)) : + original; } @Override - public String checkEmpty(RecipeKey key, InputItem value) { + public String checkEmpty(RecipeKey key, ExtendedOutputItem value) { if (value.isEmpty()) { return "Ingredient '" + key.name + "' can't be empty!"; } @@ -330,11 +341,6 @@ public String checkEmpty(RecipeKey key, InputItem value) { return ""; } - @Override - public RecipeComponent> asPatternKey() { - return MapRecipeComponent.ITEM_PATTERN_KEY; - } - @Override public String toString() { return componentType(); @@ -343,7 +349,7 @@ public String toString() { public static final ContentJS ITEM_IN = new ContentJS<>(ItemComponents.INPUT, GTRecipeCapabilities.ITEM, false); - public static final ContentJS ITEM_OUT = new ContentJS<>(INPUT_ITEM_OUT, + public static final ContentJS ITEM_OUT = new ContentJS<>(EXTENDED_OUTPUT, GTRecipeCapabilities.ITEM, true); public static final ContentJS FLUID_IN = new ContentJS<>(FLUID_INGREDIENT, GTRecipeCapabilities.FLUID, false);