diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 2c355cfbf62..5eabc26d006 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -44,9 +44,9 @@ import crafttweaker.CraftTweakerAPI; import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnmodifiableView; import java.util.ArrayList; import java.util.Arrays; @@ -80,7 +80,6 @@ public class RecipeBuilder> { protected GTRecipeCategory category; protected boolean isCTRecipe = false; protected int parallel = 0; - protected @Nullable @UnmodifiableView List> onBuildActions = null; protected EnumValidationResult recipeStatus = EnumValidationResult.VALID; protected @Nullable IRecipePropertyStorage recipePropertyStorage = null; protected boolean recipePropertyStorageErrored = false; @@ -131,8 +130,6 @@ protected RecipeBuilder(RecipeBuilder recipeBuilder) { this.EUt = recipeBuilder.EUt; this.hidden = recipeBuilder.hidden; this.category = recipeBuilder.category; - this.onBuildActions = recipeBuilder.onBuildActions == null ? null : - new ArrayList<>(recipeBuilder.onBuildActions); this.recipePropertyStorage = recipeBuilder.recipePropertyStorage == null ? null : recipeBuilder.recipePropertyStorage.copy(); if (this.recipePropertyStorage != null) { @@ -898,11 +895,6 @@ protected static String getRequiredString(int max, int actual, @NotNull String t return out; } - protected R onBuild(@NotNull List<@NotNull RecipeBuildAction> actions) { - this.onBuildActions = actions; - return (R) this; - } - /** * @deprecated Obsolete. Does not need calling. */ @@ -913,11 +905,16 @@ protected R invalidateOnBuildAction() { return (R) this; } + /** + * Build and register the recipe, if valid. + * Do not call outside of the + * {@link net.minecraftforge.event.RegistryEvent.Register} event for recipes. + * + */ + @MustBeInvokedByOverriders public void buildAndRegister() { - if (onBuildActions != null) { - for (RecipeBuildAction action : onBuildActions) { - action.accept((R) this); - } + for (RecipeBuildAction action : recipeMap.getBuildActions()) { + action.accept((R) this); } ValidationResult validationResult = build(); recipeMap.addRecipe(validationResult); diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 33ef0fa6cd6..806c0abaa92 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -38,6 +38,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Optional.Method; @@ -58,6 +59,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; @@ -121,7 +123,7 @@ public class RecipeMap> { private final Map> recipeByCategory = new Object2ObjectOpenHashMap<>(); - private @Nullable List> recipeBuildActions; + private final Map> recipeBuildActions = new Object2ObjectOpenHashMap<>(); protected @Nullable SoundEvent sound; private @Nullable RecipeMap smallRecipeMap; @@ -311,28 +313,41 @@ public RecipeMap setChanceFunction(@NotNull ChanceBoostFunction function) { /** * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. * + * @param name the unique name of the action * @param action the action to perform * @return this */ - public RecipeMap onRecipeBuild(@NotNull RecipeBuildAction action) { - if (recipeBuildActions == null) { - recipeBuildActions = new ArrayList<>(); + public RecipeMap onRecipeBuild(@NotNull ResourceLocation name, @NotNull RecipeBuildAction action) { + if (recipeBuildActions.containsKey(name)) { + throw new IllegalArgumentException("Cannot register RecipeBuildAction with duplicate name: " + name); } - recipeBuildActions.add(action); + recipeBuildActions.put(name, action); return this; } /** - * Overwrite the RecipeMap's build actions with new ones. - *

- * Use with caution. You probably want {@link #onRecipeBuild(RecipeBuildAction)} instead. - * - * @see #onRecipeBuild(RecipeBuildAction) + * @param name the name of the build action to remove + */ + public void removeBuildAction(@NotNull ResourceLocation name) { + recipeBuildActions.remove(name); + } + + /** + * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. * - * @param actions the actions to set + * @param actions the actions to perform */ - public void setOnBuildActions(@NotNull List<@NotNull RecipeBuildAction> actions) { - this.recipeBuildActions = actions; + @ApiStatus.Internal + protected void onRecipeBuild(@NotNull Map> actions) { + recipeBuildActions.putAll(actions); + } + + /** + * @return the build actions for this RecipeMap's default RecipeBuilder + */ + @ApiStatus.Internal + protected @UnmodifiableView @NotNull Collection<@NotNull RecipeBuildAction> getBuildActions() { + return this.recipeBuildActions.values(); } public RecipeMap allowEmptyOutput() { @@ -1345,7 +1360,7 @@ public String getUnlocalizedName() { } public R recipeBuilder() { - return recipeBuilderSample.copy().onBuild(recipeBuildActions); + return recipeBuilderSample.copy(); } /** diff --git a/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java b/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java index 95dc4996ddb..8995cf529aa 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java @@ -5,15 +5,16 @@ import gregtech.api.recipes.ui.RecipeMapUI; import gregtech.api.recipes.ui.RecipeMapUIFunction; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap; import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; +import java.util.Map; import static gregtech.api.recipes.ui.RecipeMapUI.computeOverlayKey; @@ -44,7 +45,7 @@ public class RecipeMapBuilder> { private SoundEvent sound; private boolean allowEmptyOutputs; - private @Nullable List> buildActions; + private @Nullable Map> buildActions; /** * @param unlocalizedName the name of the recipemap @@ -255,14 +256,17 @@ public RecipeMapBuilder(@NotNull String unlocalizedName, @NotNull B defaultRecip /** * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. * + * @param name the unique name of the action * @param action the action to perform * @return this */ - public @NotNull RecipeMapBuilder onBuild(@NotNull RecipeBuildAction action) { + public @NotNull RecipeMapBuilder onBuild(@NotNull ResourceLocation name, @NotNull RecipeBuildAction action) { if (buildActions == null) { - buildActions = new ArrayList<>(); + buildActions = new Object2ObjectOpenHashMap<>(); + } else if (buildActions.containsKey(name)) { + throw new IllegalArgumentException("Cannot register RecipeBuildAction with duplicate name: " + name); } - buildActions.add(action); + buildActions.put(name, action); return this; } @@ -280,7 +284,7 @@ public RecipeMapBuilder(@NotNull String unlocalizedName, @NotNull B defaultRecip recipeMap.allowEmptyOutput(); } if (buildActions != null) { - recipeMap.setOnBuildActions(buildActions); + recipeMap.onRecipeBuild(buildActions); } return recipeMap; } diff --git a/src/main/java/gregtech/api/recipes/RecipeMaps.java b/src/main/java/gregtech/api/recipes/RecipeMaps.java index c08ef41c165..10e1ab50522 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMaps.java +++ b/src/main/java/gregtech/api/recipes/RecipeMaps.java @@ -44,6 +44,7 @@ import stanhebben.zenscript.annotations.ZenProperty; import static gregtech.api.GTValues.*; +import static gregtech.api.util.GTUtility.gregtechId; /** * Notes: @@ -123,7 +124,7 @@ public final class RecipeMaps { .fluidOutputs(1) .progressBar(GuiTextures.PROGRESS_BAR_ARC_FURNACE) .sound(GTSoundEvents.ARC) - .onBuild(recipeBuilder -> { + .onBuild(gregtechId("arc_furnace_oxygen"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { recipeBuilder.fluidInputs(Materials.Oxygen.getFluid(recipeBuilder.getDuration())); } @@ -151,7 +152,7 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.CIRCUIT_OVERLAY, false) .progressBar(GuiTextures.PROGRESS_BAR_CIRCUIT) .sound(GTSoundEvents.ASSEMBLER) - .onBuild(recipeBuilder -> { + .onBuild(gregtechId("assembler_solder"), recipeBuilder -> { var fluidInputs = recipeBuilder.getFluidInputs(); if (fluidInputs.size() == 1 && fluidInputs.get(0).getInputFluidStack().getFluid() == Materials.SolderingAlloy.getFluid()) { @@ -160,7 +161,8 @@ public final class RecipeMaps { recipeBuilder.copy().clearFluidInputs().fluidInputs(Materials.Tin.getFluid(amount * 2)) .buildAndRegister(); } - + }) + .onBuild(gregtechId("assembler_recycling"), recipeBuilder -> { if (recipeBuilder.isWithRecycling()) { // ignore input fluids for recycling ItemStack outputStack = recipeBuilder.getOutputs().get(0); @@ -195,7 +197,8 @@ public final class RecipeMaps { @ZenProperty public static final RecipeMap ASSEMBLY_LINE_RECIPES = new RecipeMapAssemblyLine<>( "assembly_line", new AssemblyLineRecipeBuilder(), AssemblyLineUI::new) - .onRecipeBuild(AssemblyLineManager::createDefaultResearchRecipe); + .onRecipeBuild(gregtechId("default_research_recipe"), + AssemblyLineManager::createDefaultResearchRecipe); /** * Example: @@ -435,7 +438,7 @@ public final class RecipeMaps { .fluidSlotOverlay(GuiTextures.VIAL_OVERLAY_2, true) .progressBar(GuiTextures.PROGRESS_BAR_ARROW_MULTIPLE) .sound(GTValues.FOOLS.get() ? GTSoundEvents.SCIENCE : GTSoundEvents.CHEMICAL_REACTOR) - .onBuild(recipeBuilder -> RecipeMaps.LARGE_CHEMICAL_RECIPES.recipeBuilder() + .onBuild(gregtechId("lcr_copy"), recipeBuilder -> RecipeMaps.LARGE_CHEMICAL_RECIPES.recipeBuilder() .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) .fluidInputs(recipeBuilder.getFluidInputs()) .outputs(recipeBuilder.getOutputs()) @@ -484,7 +487,7 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.CIRCUIT_OVERLAY, false) .progressBar(GuiTextures.PROGRESS_BAR_CIRCUIT_ASSEMBLER) .sound(GTSoundEvents.ASSEMBLER) - .onBuild(recipeBuilder -> { + .onBuild(gregtechId("circuit_assembler_solder"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { recipeBuilder.copy() .fluidInputs(Materials.SolderingAlloy.getFluid(Math.max(1, @@ -606,7 +609,7 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.DUST_OVERLAY, true, true) .progressBar(GuiTextures.PROGRESS_BAR_SLICE) .sound(GTSoundEvents.CUT) - .onBuild(recipeBuilder -> { + .onBuild(gregtechId("cutter_fluid"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { int duration = recipeBuilder.getDuration(); int eut = recipeBuilder.getEUt();