From cac58d42e5785999b74785ce6d78f9110e0719f1 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Sun, 16 Jun 2024 02:16:56 -0700 Subject: [PATCH] Immersive Engineering Crusher Recipe Secondary Output (#169) * resolve #167 * simplify float array excavator code * use fastutil FloatArrayList for Crusher and Excavator --- examples/postInit/immersiveengineering.groovy | 10 ++++++- .../mods/immersiveengineering/Crusher.java | 30 ++++++++++++++++++- .../mods/immersiveengineering/Excavator.java | 10 +++---- .../assets/groovyscript/lang/en_us.lang | 4 ++- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/examples/postInit/immersiveengineering.groovy b/examples/postInit/immersiveengineering.groovy index ad9895b28..10dbf4a68 100644 --- a/examples/postInit/immersiveengineering.groovy +++ b/examples/postInit/immersiveengineering.groovy @@ -116,7 +116,7 @@ mods.immersiveengineering.coke_oven.recipeBuilder() // Crusher: -// Converts an input itemstack into an output itemstack, consuming energy. +// Converts an input itemstack into an output itemstack with optional additional chanced item outputs, consuming energy. mods.immersiveengineering.crusher.removeByInput(item('immersiveengineering:material:7')) mods.immersiveengineering.crusher.removeByOutput(item('minecraft:sand')) @@ -128,6 +128,14 @@ mods.immersiveengineering.crusher.recipeBuilder() .energy(100) .register() +mods.immersiveengineering.crusher.recipeBuilder() + .input(item('minecraft:diamond_block')) + .output(item('minecraft:diamond')) + .secondaryOutput(item('minecraft:gold_ingot')) + .secondaryOutput(item('minecraft:gold_ingot'), 0.3) + .energy(100) + .register() + // Excavator: diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Crusher.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Crusher.java index 56ad2ccac..089392fe3 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Crusher.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Crusher.java @@ -9,15 +9,20 @@ import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import it.unimi.dsi.fastutil.floats.FloatArrayList; import net.minecraft.item.ItemStack; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; @RegistryDescription public class Crusher extends VirtualizedRegistry { - @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay')).energy(100)")) + @RecipeBuilderDescription(example = { + @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay')).energy(100)"), + @Example(".input(item('minecraft:diamond_block')).output(item('minecraft:diamond')).secondaryOutput(item('minecraft:gold_ingot')).secondaryOutput(item('minecraft:gold_ingot'), 0.3).energy(100)") + }) public static RecipeBuilder recipeBuilder() { return new RecipeBuilder(); } @@ -103,9 +108,25 @@ public void removeAll() { @Property(property = "output", valid = @Comp("1")) public static class RecipeBuilder extends AbstractRecipeBuilder { + @Property(valid = @Comp("secondaryOutputChances")) + private final List secondaryOutputItems = new ArrayList<>(); + @Property(valid = @Comp("secondaryOutputItems")) + private final FloatArrayList secondaryOutputChances = new FloatArrayList(); @Property(valid = @Comp(value = "0", type = Comp.Type.GTE)) private int energy; + @RecipeBuilderMethodDescription(field = {"secondaryOutputItems", "secondaryOutputChances"}) + public RecipeBuilder secondaryOutput(ItemStack item) { + return this.secondaryOutput(item, 1); + } + + @RecipeBuilderMethodDescription(field = {"secondaryOutputItems", "secondaryOutputChances"}) + public RecipeBuilder secondaryOutput(ItemStack item, float chance) { + this.secondaryOutputItems.add(item); + this.secondaryOutputChances.add(chance); + return this; + } + @RecipeBuilderMethodDescription public RecipeBuilder energy(int energy) { this.energy = energy; @@ -121,6 +142,8 @@ public String getErrorMsg() { public void validate(GroovyLog.Msg msg) { validateItems(msg, 1, 1, 1, 1); validateFluids(msg); + secondaryOutputChances.trim(); + msg.add(secondaryOutputItems.size() != secondaryOutputChances.size(), "secondaryOutputItems and secondaryOutputChances must be of equal length, yet secondaryOutputItems was {} and secondaryOutputChances was {}", secondaryOutputItems.size(), secondaryOutputChances.size()); if (energy < 0) energy = 200; } @@ -129,6 +152,11 @@ public void validate(GroovyLog.Msg msg) { public @Nullable CrusherRecipe register() { if (!validate()) return null; CrusherRecipe recipe = new CrusherRecipe(output.get(0), input.get(0), energy); + if (!secondaryOutputItems.isEmpty()) { + recipe.secondaryOutput = secondaryOutputItems.toArray(new ItemStack[0]); + recipe.secondaryChance = secondaryOutputChances.elements(); + recipe.getItemOutputs().addAll(secondaryOutputItems); + } ModSupport.IMMERSIVE_ENGINEERING.get().crusher.add(recipe); return recipe; } diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Excavator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Excavator.java index 181d4059e..0775a97f1 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Excavator.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/immersiveengineering/Excavator.java @@ -9,6 +9,7 @@ import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder; import com.cleanroommc.groovyscript.registry.VirtualizedRegistry; +import it.unimi.dsi.fastutil.floats.FloatArrayList; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Nullable; @@ -142,7 +143,7 @@ public static class RecipeBuilder extends AbstractRecipeBuilder ores = new ArrayList<>(); @Property(valid = @Comp("ores")) - private final List chances = new ArrayList<>(); + private final FloatArrayList chances = new FloatArrayList(); @Property private final List dimensions = new ArrayList<>(); @Property(ignoresInheritedMethods = true) @@ -230,6 +231,7 @@ public void validate(GroovyLog.Msg msg) { validateItems(msg); validateFluids(msg); msg.add(fail < 0 || fail > 1, "fail must be a float between 0 and 1, yet it was {}", fail); + chances.trim(); msg.add(ores.size() != chances.size(), "ores and chances must be of equal length, yet ores was {} and chances was {}", ores.size(), chances.size()); } @@ -237,11 +239,7 @@ public void validate(GroovyLog.Msg msg) { @RecipeBuilderRegistrationMethod public @Nullable ExcavatorHandler.MineralMix register() { if (!validate()) return null; - float[] chanceArray = new float[chances.size()]; - for (int i = 0; i < chances.size(); i++) { - chanceArray[i] = chances.get(i); - } - ExcavatorHandler.MineralMix recipe = new ExcavatorHandler.MineralMix(name, fail, ores.toArray(new String[0]), chanceArray); + ExcavatorHandler.MineralMix recipe = new ExcavatorHandler.MineralMix(name, fail, ores.toArray(new String[0]), chances.elements()); int[] dims = dimensions.stream().mapToInt(Integer::intValue).toArray(); if (dims != null) { diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index b98e5ff1b..d5a581f42 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -933,9 +933,11 @@ groovyscript.wiki.immersiveengineering.coke_oven.creosote.value=Sets the amount groovyscript.wiki.immersiveengineering.coke_oven.time.value=Sets the time in ticks the recipe takes to process groovyscript.wiki.immersiveengineering.crusher.title=Crusher -groovyscript.wiki.immersiveengineering.crusher.description=Converts an input itemstack into an output itemstack, consuming energy. +groovyscript.wiki.immersiveengineering.crusher.description=Converts an input itemstack into an output itemstack with optional additional chanced item outputs, consuming energy. groovyscript.wiki.immersiveengineering.crusher.add=Adds recipes in the format `output`, `input`, `energy` groovyscript.wiki.immersiveengineering.crusher.energy.value=Sets the amount of power consumed to complete the recipe +groovyscript.wiki.immersiveengineering.crusher.secondaryOutputItems.value=Sets the additional items output by the recipe, if any +groovyscript.wiki.immersiveengineering.crusher.secondaryOutputChances.value=Sets the chance of the respective additional items output by the recipe groovyscript.wiki.immersiveengineering.excavator.title=Excavator groovyscript.wiki.immersiveengineering.excavator.description=Adds a Mineral Mix with the given name, weight, fail chance, ores, and allowed dimensions. A Mineral Mix can be mined by an Excavator Multiblock and scanned via a Core Sample Drill.