From 9aa1d07e655f97ad7c22479eded9c7460af42e18 Mon Sep 17 00:00:00 2001 From: tier940 Date: Sun, 4 Jan 2026 12:10:45 +0900 Subject: [PATCH 1/3] =?UTF-8?q?DEDA=E9=80=A3=E6=90=BA=E3=81=AE=E3=83=AA?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +- .../ae/recipes/AEMaterialsRecipe.java | 6 +- .../integration/deda/DEDAConfigHolder.java | 9 + .../core/integration/deda/DEDAConstants.java | 56 ++++++ .../integration/deda/DEDARecipeHelper.java | 38 ++++ .../deda/provider/DEDAJEIProvider.java | 20 +- .../recipemaps/GTEDraconicRecipeMaps.java | 74 ++----- .../recipemaps/RecipeMapDraconicFusion.java | 60 ++++-- .../deda/recipemaps/UpgradeRecipeCache.java | 184 ++++++++++++++++++ .../deda/recipes/DraconicMaterialsRecipe.java | 3 - .../deda/recipes/DraconicTierupRecipe.java | 106 +++++----- .../deda/recipes/DraconicUpgradeRecipe.java | 10 +- .../gcym/AlloyBlastRecipeProducerMixin.java | 8 +- 13 files changed, 421 insertions(+), 159 deletions(-) create mode 100644 src/main/java/com/github/gtexpert/core/integration/deda/DEDAConstants.java create mode 100644 src/main/java/com/github/gtexpert/core/integration/deda/DEDARecipeHelper.java create mode 100644 src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/UpgradeRecipeCache.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d0547b..47df10d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +# 2.5.7 +- Mining Level and Tool Suitability Adjustments for Blocks Added via Chisel [#343](https://github.com/GTModpackTeam/GTExpert-Core/pull/343) + +* * * + # 2.5.6 - Fix Implosion logic -- Mining Level and Tool Suitability Adjustments for Blocks Added via Chisel [#343](https://github.com/GTModpackTeam/GTExpert-Core/pull/343) * * * diff --git a/src/main/java/com/github/gtexpert/core/integration/ae/recipes/AEMaterialsRecipe.java b/src/main/java/com/github/gtexpert/core/integration/ae/recipes/AEMaterialsRecipe.java index 4756bbef..187d42a1 100644 --- a/src/main/java/com/github/gtexpert/core/integration/ae/recipes/AEMaterialsRecipe.java +++ b/src/main/java/com/github/gtexpert/core/integration/ae/recipes/AEMaterialsRecipe.java @@ -1,6 +1,6 @@ package com.github.gtexpert.core.integration.ae.recipes; -import static com.github.gtexpert.core.integration.deda.recipes.DraconicMaterialsRecipe.ABFDurationMultiplier; +import static com.github.gtexpert.core.integration.deda.DEDAConstants.ABF_DURATION_MULTIPLIER; import static gregtech.api.GTValues.*; import static gregtech.api.unification.ore.OrePrefix.*; @@ -348,7 +348,7 @@ public static void init() { .fluidInputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 200)) .fluidOutputs(GTEMaterials.FluixAlloy.getFluid(GCYMFluidStorageKeys.MOLTEN, 1152)) .blastFurnaceTemp(propertyFluixAlloy.getBlastTemperature()) - .duration((int) ((durationFluixAlloy * 0.67 * ABFDurationMultiplier) / 2)) + .duration((int) ((durationFluixAlloy * 0.67 * ABF_DURATION_MULTIPLIER) / 2)) .EUt(VA[GTEValues.ae2VoltageTier]) .buildAndRegister(); } @@ -362,7 +362,7 @@ public static void init() { .fluidInputs(Materials.Nitrogen.getFluid(6000)) .fluidOutputs(GTEMaterials.FluixAlloy.getFluid(GCYMFluidStorageKeys.MOLTEN, 1152)) .blastFurnaceTemp(propertyFluixAlloy.getBlastTemperature()) - .duration((int) (durationFluixAlloy * 0.67 * ABFDurationMultiplier)).EUt(VA[GTEValues.ae2VoltageTier]) + .duration((int) (durationFluixAlloy * 0.67 * ABF_DURATION_MULTIPLIER)).EUt(VA[GTEValues.ae2VoltageTier]) .buildAndRegister(); GCYMRecipeMaps.ALLOY_BLAST_RECIPES.recipeBuilder() .circuitMeta(4) diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConfigHolder.java b/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConfigHolder.java index d056415a..aa14be7f 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConfigHolder.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConfigHolder.java @@ -15,4 +15,13 @@ public class DEDAConfigHolder { "The material is also adjusted to each voltage.", "Default: 6 (LuV)" }) @Config.RangeInt(min = 3, max = 6) public static int voltageTier = 6; + + @Config.Comment({ "Enable verbose logging for upgrade recipe lookup debugging.", + "Useful for troubleshooting recipe matching issues.", "Default: false" }) + public static boolean debugRecipeLookup = false; + + @Config.Comment({ "Enable caching for upgrade recipe lookups.", + "Improves performance by indexing recipes by catalyst item type.", + "Disable if you experience recipe matching issues.", "Default: true" }) + public static boolean enableUpgradeRecipeCache = true; } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConstants.java b/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConstants.java new file mode 100644 index 00000000..2056c647 --- /dev/null +++ b/src/main/java/com/github/gtexpert/core/integration/deda/DEDAConstants.java @@ -0,0 +1,56 @@ +package com.github.gtexpert.core.integration.deda; + +import net.minecraftforge.fluids.FluidStack; + +import gregicality.multiblocks.api.fluids.GCYMFluidStorageKeys; + +import com.github.gtexpert.core.api.unification.material.GTEMaterials; + +/** + * Constants and helpers for DEDA (Draconic Evolution / Draconic Additions) integration. + */ +public final class DEDAConstants { + + private DEDAConstants() {} + + // Alloy Blast Furnace constants + public static final int ABF_PYROTHEUM_AMOUNT = 200; + public static final double ABF_DURATION_MULTIPLIER = 0.5; + + // Recipe durations (ticks) + public static final int DURATION_WYVERN = 200; + public static final int DURATION_DRACONIC = 400; + public static final int DURATION_CHAOTIC = 600; + + public static FluidStack getCryotheum(DraconicTier tier) { + return switch (tier) { + case WYVERN -> GTEMaterials.Cryotheum.getFluid(16000); + case DRACONIC -> GTEMaterials.Cryotheum.getFluid(32000); + case CHAOTIC -> GTEMaterials.Cryotheum.getFluid(48000); + }; + } + + public static FluidStack getPyrotheum(DraconicTier tier) { + return switch (tier) { + case WYVERN -> GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 4000); + case DRACONIC -> GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 8000); + case CHAOTIC -> GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 12000); + }; + } + + /** + * Draconic Evolution tool/armor tiers. + */ + public enum DraconicTier { + + WYVERN(0), + DRACONIC(1), + CHAOTIC(2); + + public final int voltageOffset; + + DraconicTier(int voltageOffset) { + this.voltageOffset = voltageOffset; + } + } +} diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/DEDARecipeHelper.java b/src/main/java/com/github/gtexpert/core/integration/deda/DEDARecipeHelper.java new file mode 100644 index 00000000..349127d6 --- /dev/null +++ b/src/main/java/com/github/gtexpert/core/integration/deda/DEDARecipeHelper.java @@ -0,0 +1,38 @@ +package com.github.gtexpert.core.integration.deda; + +import static gregtech.api.GTValues.VA; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import gregtech.api.recipes.ingredients.GTRecipeInput; +import gregtech.api.recipes.ingredients.GTRecipeItemInput; +import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition; +import gregtech.api.recipes.ingredients.nbtmatch.NBTMatcher; + +import com.github.gtexpert.core.api.GTEValues; +import com.github.gtexpert.core.integration.deda.DEDAConstants.DraconicTier; + +/** + * Helper methods for DEDA integration recipes. + */ +public final class DEDARecipeHelper { + + private DEDARecipeHelper() {} + + public static int voltage(DraconicTier tier) { + return VA[GTEValues.dedaVoltageTier + tier.voltageOffset]; + } + + public static FluidStack cryotheum(DraconicTier tier) { + return DEDAConstants.getCryotheum(tier); + } + + public static FluidStack pyrotheum(DraconicTier tier) { + return DEDAConstants.getPyrotheum(tier); + } + + public static GTRecipeInput inputWithAnyNBT(ItemStack stack) { + return new GTRecipeItemInput(stack).setNBTMatchingCondition(NBTMatcher.ANY, NBTCondition.ANY); + } +} diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/provider/DEDAJEIProvider.java b/src/main/java/com/github/gtexpert/core/integration/deda/provider/DEDAJEIProvider.java index 81735de4..91c0a487 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/provider/DEDAJEIProvider.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/provider/DEDAJEIProvider.java @@ -19,14 +19,18 @@ public class DEDAJEIProvider implements IModPlugin { @Override public void register(@NotNull IModRegistry registry) { if (GTEValues.isModLoadedDEDA()) { - registry.addRecipeCatalyst(DEDAMetaTileEntities.DRACONIUM_FUSION.getStackForm(), - GTValues.MODID + ":" + GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_FAKE_RECIPES.unlocalizedName); - registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), GTValues.MODID + - ":" + GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_TIER_UP_FAKE_RECIPES.unlocalizedName); - registry.addRecipeCatalyst(DEDAMetaTileEntities.DRACONIUM_FUSION.getStackForm(), - GTValues.MODID + ":" + GTEDraconicRecipeMaps.DRACONIC_FUSION_UPGRADE_FAKE_RECIPES.unlocalizedName); - registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), GTValues.MODID + - ":" + GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_UPGRADE_FAKE_RECIPES.unlocalizedName); + String fusionCategory = GTValues.MODID + ":" + + GTEDraconicRecipeMaps.DRACONIUM_FUSION_RECIPES.unlocalizedName; + String tierUpCategory = GTValues.MODID + ":" + + GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_RECIPES.unlocalizedName; + String upgradeCategory = GTValues.MODID + ":" + + GTEDraconicRecipeMaps.DRACONIC_FUSION_UPGRADE_RECIPES.unlocalizedName; + + registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), fusionCategory); + registry.addRecipeCatalyst(DEDAMetaTileEntities.DRACONIUM_FUSION.getStackForm(), tierUpCategory); + registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), tierUpCategory); + registry.addRecipeCatalyst(DEDAMetaTileEntities.DRACONIUM_FUSION.getStackForm(), upgradeCategory); + registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), upgradeCategory); } } } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/GTEDraconicRecipeMaps.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/GTEDraconicRecipeMaps.java index 6a8c0ec1..03b0ce7b 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/GTEDraconicRecipeMaps.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/GTEDraconicRecipeMaps.java @@ -19,68 +19,29 @@ public class GTEDraconicRecipeMaps { /** - * Fake recipe map to show tier-up recipes for draconic fusion on JEI. - * In order to preserve upgrade info NBT, actual recipe is handled by {@link RecipeMapDraconicFusion}. + * Unified recipe map to show all tier-up recipes for draconic fusion on JEI. + * Consolidates recipes from both Draconic and Awakened fusion machines. + * Actual recipe execution is handled by {@link RecipeMapDraconicFusion}. */ - public static final RecipeMap DRACONIC_FUSION_TIER_UP_FAKE_RECIPES = new RecipeMapDraconicUpgrade<>( + @ZenProperty + public static final RecipeMap DRACONIC_FUSION_TIER_UP_RECIPES = new RecipeMapDraconicUpgrade<>( "draconic_fusion_tier_up", 6, 3, 3, 1, new TierUpRecipeBuilder(), false) - .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) - .onRecipeBuild( - recipeBuilder -> GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_TIER_UP_FAKE_RECIPES - .recipeBuilder() - .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) - .fluidInputs(recipeBuilder.getFluidInputs()) - .outputs(recipeBuilder.getOutputs()) - .fluidOutputs(recipeBuilder.getFluidOutputs()) - .duration(recipeBuilder.getDuration()) - .EUt(recipeBuilder.getEUt()) - .catalyst(recipeBuilder.getCatalyst()) - .result(recipeBuilder.getResult()) - .buildAndRegister()); - - /** - * Fake recipe map to show tier-up recipes for draconic fusion on JEI. - * In order to preserve upgrade info NBT, actual recipe is handled by {@link RecipeMapDraconicFusion}. - */ - public static final RecipeMap AWAKENED_DRACONIC_FUSION_TIER_UP_FAKE_RECIPES = new RecipeMapDraconicUpgrade<>( - "awakened_draconic_fusion_tier_up", 6, 3, 3, 1, new TierUpRecipeBuilder(), false) - .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) - .setSmallRecipeMap(DRACONIC_FUSION_TIER_UP_FAKE_RECIPES); + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL); /** - * Fake recipe map to show upgrade recipes for draconic fusion on JEI. - * In order to preserve upgrade info NBT, actual recipe is handled by {@link RecipeMapDraconicFusion}. + * Unified recipe map to show all upgrade recipes for draconic fusion on JEI. + * Consolidates recipes from both Draconic and Awakened fusion machines. + * Actual recipe execution is handled by {@link RecipeMapDraconicFusion}. */ - public static final RecipeMap DRACONIC_FUSION_UPGRADE_FAKE_RECIPES = new RecipeMapDraconicUpgrade<>( + @ZenProperty + public static final RecipeMap DRACONIC_FUSION_UPGRADE_RECIPES = new RecipeMapDraconicUpgrade<>( "draconic_fusion_upgrade", 6, 3, 3, 1, new UpgradeRecipeBuilder(), false) - .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) - .onRecipeBuild( - recipeBuilder -> GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_UPGRADE_FAKE_RECIPES - .recipeBuilder() - .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) - .fluidInputs(recipeBuilder.getFluidInputs()) - .outputs(recipeBuilder.getOutputs()) - .fluidOutputs(recipeBuilder.getFluidOutputs()) - .duration(recipeBuilder.getDuration()) - .EUt(recipeBuilder.getEUt()) - .catalyst(recipeBuilder.getCatalyst()) - .upgradeName(recipeBuilder.getUpgradeName()) - .level(recipeBuilder.getCurrentLevel()) - .buildAndRegister()); - - /** - * Fake recipe map to show upgrade recipes for draconic fusion on JEI. - * In order to preserve upgrade info NBT, actual recipe is handled by {@link RecipeMapDraconicFusion}. - */ - public static final RecipeMap AWAKENED_DRACONIC_FUSION_UPGRADE_FAKE_RECIPES = new RecipeMapDraconicUpgrade<>( - "awakened_draconic_fusion_upgrade", 6, 3, 3, 1, new UpgradeRecipeBuilder(), false) - .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) - .setSmallRecipeMap(DRACONIC_FUSION_UPGRADE_FAKE_RECIPES); + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL); @ZenProperty public static final RecipeMap DRACONIUM_FUSION_RECIPES = new RecipeMapDraconicFusion( - "draconium_fusion", 6, 3, 3, 1, new SimpleRecipeBuilder(), false, DRACONIC_FUSION_TIER_UP_FAKE_RECIPES, - DRACONIC_FUSION_UPGRADE_FAKE_RECIPES) + "draconium_fusion", 6, 3, 3, 1, new SimpleRecipeBuilder(), false, + DRACONIC_FUSION_TIER_UP_RECIPES, DRACONIC_FUSION_UPGRADE_RECIPES) .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) .setSound(GTSoundEvents.ELECTROLYZER) .onRecipeBuild( @@ -96,9 +57,8 @@ public class GTEDraconicRecipeMaps { @ZenProperty public static final RecipeMap AWAKENED_DRACONIUM_FUSION_RECIPES = new RecipeMapDraconicFusion( - "awakened_draconium_fusion", 6, 3, 3, 1, new SimpleRecipeBuilder(), false, - AWAKENED_DRACONIC_FUSION_TIER_UP_FAKE_RECIPES, AWAKENED_DRACONIC_FUSION_UPGRADE_FAKE_RECIPES) + "awakened_draconium_fusion", 6, 3, 3, 1, new SimpleRecipeBuilder(), true, + DRACONIC_FUSION_TIER_UP_RECIPES, DRACONIC_FUSION_UPGRADE_RECIPES) .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) - .setSound(GTSoundEvents.ELECTROLYZER) - .setSmallRecipeMap(DRACONIUM_FUSION_RECIPES); + .setSound(GTSoundEvents.ELECTROLYZER); } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicFusion.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicFusion.java index 455f0075..1e60d519 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicFusion.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicFusion.java @@ -26,6 +26,7 @@ import gregtech.api.recipes.builders.SimpleRecipeBuilder; import com.github.gtexpert.core.api.util.GTELog; +import com.github.gtexpert.core.integration.deda.DEDAConfigHolder; import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeBuilder; import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeProperty; import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeBuilder; @@ -38,6 +39,9 @@ public class RecipeMapDraconicFusion extends RecipeMap { private final RecipeMap tierUpRecipeMap; private final RecipeMap upgradeRecipeMap; + /** Cache for upgrade recipe lookups - improves O(n) to O(m) where m << n */ + private final UpgradeRecipeCache upgradeCache = new UpgradeRecipeCache(); + public RecipeMapDraconicFusion(@NotNull String unlocalizedName, int maxInputs, int maxOutputs, int maxFluidInputs, int maxFluidOutputs, @NotNull SimpleRecipeBuilder defaultRecipeBuilder, boolean isHidden, RecipeMap tierUpRecipeMap, @@ -63,25 +67,51 @@ public Recipe findRecipe(long voltage, List inputs, List tierUpRecipe.getProperty(TierUpRecipeProperty.getInstance(), null)); } - // We need to manually search RecipeMap here. - // - // RecipeMap#recurseIngredientTreeFindRecipe only searches branch first found (`Either result = - // targetMap.get(obj);`). - // This is fine in most of the situations, but here it's not; - // - // When recipes get added, many of the catalyst objects are not equal each other, as they don't have level-0 tag - // and UpgradeRecipeBuilder#EQUAL_TO_RECURSIVE returns false, hence all the recipes are added as separate nodes. - // example: #lookup -> [draconic_helm -> [tool_upgrade@9], draconic_helm -> [tool_upgrade@8], ...], instead of - // [draconic_helm -> [tool_upgrade@9, tool_upgrade@8]] - // But when searching recipe, an itemstack can match (`equals`) to multiple branches. - // example: when draconic_helm with no upgrade is passed as input, it can match to all branches accepts basic - // upgrade + // Use cached lookup for upgrade recipes if enabled + // This improves performance from O(n) to O(m) where m is the number of recipes + // for the specific catalyst item type, instead of all upgrade recipes + Recipe upgradeRecipe = findUpgradeRecipe(voltage, inputs, fluidInputs); + if (upgradeRecipe != null) { + return setupOutput(upgradeRecipe, inputs, + upgradeRecipe.getProperty(UpgradeRecipeProperty.getInstance(), null)); + } + + return null; + } + + /** + * Find upgrade recipe using cache if enabled, otherwise fall back to linear search. + */ + @Nullable + private Recipe findUpgradeRecipe(long voltage, List inputs, List fluidInputs) { + if (DEDAConfigHolder.enableUpgradeRecipeCache) { + // Ensure cache is built (lazy initialization) + if (!upgradeCache.isInitialized()) { + upgradeCache.buildCache(upgradeRecipeMap); + } + return upgradeCache.findRecipe(voltage, inputs, fluidInputs); + } else { + // Fallback to original O(n) linear search + return findUpgradeRecipeLinear(voltage, inputs, fluidInputs); + } + } + + /** + * Linear search for upgrade recipes. + * O(n) complexity where n is the total number of upgrade recipes. + *

+ * We need to manually search RecipeMap here because: + * RecipeMap#recurseIngredientTreeFindRecipe only searches branch first found. + * When recipes get added, catalyst objects with different NBT states create separate branches. + * But when searching, an itemstack can match to multiple branches. + */ + @Nullable + private Recipe findUpgradeRecipeLinear(long voltage, List inputs, List fluidInputs) { for (Recipe recipe : upgradeRecipeMap.getRecipeList()) { if (recipe.getEUt() <= voltage && recipe.matches(false, inputs, fluidInputs)) { - return setupOutput(recipe, inputs, recipe.getProperty(UpgradeRecipeProperty.getInstance(), null)); + return recipe; } } - return null; } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/UpgradeRecipeCache.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/UpgradeRecipeCache.java new file mode 100644 index 00000000..35bc8a1b --- /dev/null +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/UpgradeRecipeCache.java @@ -0,0 +1,184 @@ +package com.github.gtexpert.core.integration.deda.recipemaps; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.Nullable; + +import com.brandon3055.draconicevolution.api.itemupgrade.IUpgradableItem; + +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.ingredients.GTRecipeInput; + +import com.github.gtexpert.core.api.util.GTELog; +import com.github.gtexpert.core.integration.deda.DEDAConfigHolder; + +/** + * Cache for upgrade recipe lookups to improve performance. + *

+ * The standard RecipeMap tree indexing doesn't work well for upgrade recipes + * because catalyst items with different NBT states create separate branches. + * This cache indexes recipes by catalyst item type (ignoring NBT) to allow + * O(m) lookup where m is the number of recipes for that specific item, + * instead of O(n) for all upgrade recipes. + *

+ * The cache is built lazily on first recipe lookup after all recipes are registered. + */ +public class UpgradeRecipeCache { + + /** + * Index: ItemStackKey (item + meta, ignoring NBT) -> List of applicable upgrade recipes + */ + private final Map> catalystIndex = new HashMap<>(); + + private boolean initialized = false; + private int totalRecipes = 0; + private int indexedItems = 0; + + /** + * Build the cache from upgrade recipe map. + * Called once after all recipes are registered (lazy initialization). + * + * @param upgradeRecipeMap the recipe map containing upgrade recipes + */ + public void buildCache(RecipeMap upgradeRecipeMap) { + if (initialized) return; + + long startTime = System.currentTimeMillis(); + + for (Recipe recipe : upgradeRecipeMap.getRecipeList()) { + // Get the catalyst input (first input slot by convention in upgrade recipes) + if (recipe.getInputs().isEmpty()) continue; + + GTRecipeInput catalystInput = recipe.getInputs().get(0); + for (ItemStack stack : catalystInput.getInputStacks()) { + // Only index upgradable items + if (!(stack.getItem() instanceof IUpgradableItem)) continue; + + ItemStackKey key = new ItemStackKey(stack.getItem(), stack.getMetadata()); + catalystIndex.computeIfAbsent(key, k -> new ArrayList<>()).add(recipe); + } + totalRecipes++; + } + + indexedItems = catalystIndex.size(); + initialized = true; + + long elapsed = System.currentTimeMillis() - startTime; + if (DEDAConfigHolder.debugRecipeLookup) { + GTELog.logger.info("UpgradeRecipeCache built: {} recipes indexed across {} item types in {}ms", + totalRecipes, indexedItems, elapsed); + } + } + + /** + * Find matching upgrade recipe for given inputs. + * O(m) where m is the number of recipes for this specific catalyst item, + * instead of O(n) for all upgrade recipes. + * + * @param voltage maximum voltage + * @param inputs item inputs + * @param fluidInputs fluid inputs + * @return matching recipe or null if not found + */ + @Nullable + public Recipe findRecipe(long voltage, List inputs, List fluidInputs) { + for (ItemStack input : inputs) { + if (!(input.getItem() instanceof IUpgradableItem)) continue; + + ItemStackKey key = new ItemStackKey(input.getItem(), input.getMetadata()); + List candidates = catalystIndex.get(key); + + if (candidates == null) continue; + + if (DEDAConfigHolder.debugRecipeLookup) { + GTELog.logger.debug("Checking {} candidate recipes for {}", candidates.size(), key); + } + + for (Recipe recipe : candidates) { + if (recipe.getEUt() <= voltage && recipe.matches(false, inputs, fluidInputs)) { + return recipe; + } + } + } + return null; + } + + /** + * Check if the cache has been initialized. + * + * @return true if cache is ready + */ + public boolean isInitialized() { + return initialized; + } + + /** + * Get the total number of indexed recipes. + * + * @return recipe count + */ + public int getTotalRecipes() { + return totalRecipes; + } + + /** + * Get the number of unique item types indexed. + * + * @return item type count + */ + public int getIndexedItems() { + return indexedItems; + } + + /** + * Clear the cache. Useful for testing or if recipes need to be reloaded. + */ + public void clear() { + catalystIndex.clear(); + initialized = false; + totalRecipes = 0; + indexedItems = 0; + } + + /** + * Key for indexing items by type and metadata, ignoring NBT. + * This allows grouping all upgrade recipes for the same item type together. + */ + private static final class ItemStackKey { + + private final Item item; + private final int meta; + + ItemStackKey(Item item, int meta) { + this.item = item; + this.meta = meta; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ItemStackKey that = (ItemStackKey) o; + return meta == that.meta && Objects.equals(item, that.item); + } + + @Override + public int hashCode() { + return Objects.hash(item, meta); + } + + @Override + public String toString() { + return item.getRegistryName() + "@" + meta; + } + } +} diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicMaterialsRecipe.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicMaterialsRecipe.java index 85eb5c3c..e9b4218b 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicMaterialsRecipe.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicMaterialsRecipe.java @@ -26,9 +26,6 @@ public class DraconicMaterialsRecipe { - public static final int ABFPyrotheumAmount = 200; - public static final double ABFDurationMultiplier = 0.5; - public static void init() { // ######################################## // Draconic Evolution diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicTierupRecipe.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicTierupRecipe.java index 2ba064d8..2ac7caac 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicTierupRecipe.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicTierupRecipe.java @@ -1,6 +1,5 @@ package com.github.gtexpert.core.integration.deda.recipes; -import static gregtech.api.GTValues.VA; import static gregtech.api.unification.ore.OrePrefix.plate; import net.foxmcloud.draconicadditions.DAFeatures; @@ -10,7 +9,6 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.recipes.ModHandler; -import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.api.recipes.ingredients.GTRecipeItemInput; import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition; @@ -19,12 +17,13 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; -import gregicality.multiblocks.api.fluids.GCYMFluidStorageKeys; - import com.github.gtexpert.core.api.GTEValues; import com.github.gtexpert.core.api.unification.material.GTEMaterials; import com.github.gtexpert.core.api.util.GTEUtility; import com.github.gtexpert.core.api.util.Mods; +import com.github.gtexpert.core.integration.deda.DEDAConstants; +import com.github.gtexpert.core.integration.deda.DEDAConstants.DraconicTier; +import com.github.gtexpert.core.integration.deda.DEDARecipeHelper; import com.github.gtexpert.core.integration.deda.recipemaps.GTEDraconicRecipeMaps; import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeBuilder; @@ -39,7 +38,7 @@ public static void init() { NBTTagType.COMPOUND, ToolHelper.TOOL_TAG_KEY, NBTCondition.create( NBTTagType.STRING, "Material", GTEValues.MODID + ":draconium"))), new ItemStack(DEFeatures.wyvernAxe), - Tier.WYVERN, 2); + DraconicTier.WYVERN, 2); // Pickaxe of the Wyvern ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_pick")); @@ -49,7 +48,7 @@ public static void init() { NBTTagType.COMPOUND, ToolHelper.TOOL_TAG_KEY, NBTCondition.create( NBTTagType.STRING, "Material", GTEValues.MODID + ":draconium"))), new ItemStack(DEFeatures.wyvernPick), - Tier.WYVERN, 2); + DraconicTier.WYVERN, 2); // Shovel of the Wyvern ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_shovel")); @@ -59,13 +58,13 @@ public static void init() { NBTTagType.COMPOUND, ToolHelper.TOOL_TAG_KEY, NBTCondition.create( NBTTagType.STRING, "Material", GTEValues.MODID + ":draconium"))), new ItemStack(DEFeatures.wyvernShovel), - Tier.WYVERN, 2); + DraconicTier.WYVERN, 2); // Sword of the Wyvern ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_sword")); addTierUpRecipe(MetaItems.NANO_SABER.getStackForm(), new ItemStack(DEFeatures.wyvernSword), - Tier.WYVERN, 2); + DraconicTier.WYVERN, 2); // Bow of the Wyvern ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_bow")); @@ -75,21 +74,21 @@ public static void init() { Mods.Vanilla.getItem("bow")) .setNBTMatchingCondition(NBTMatcher.ANY, NBTCondition.ANY), new ItemStack(DEFeatures.wyvernBow), - Tier.WYVERN, 2); + DraconicTier.WYVERN, 2); // Wyvern Helm ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_helm")); addTierUpRecipe( MetaItems.QUANTUM_HELMET.getStackForm(), new ItemStack(DEFeatures.wyvernHelm), - Tier.WYVERN, 6); + DraconicTier.WYVERN, 6); // Wyvern Chest ModHandler.removeRecipeByName(Mods.DraconicEvolution.getResource("wyvern_chest")); addTierUpRecipe( MetaItems.QUANTUM_CHESTPLATE_ADVANCED.getStackForm(), new ItemStack(DEFeatures.wyvernChest), - Tier.WYVERN, + DraconicTier.WYVERN, 6); // Wyvern Legs @@ -97,7 +96,7 @@ public static void init() { addTierUpRecipe( MetaItems.QUANTUM_LEGGINGS.getStackForm(), new ItemStack(DEFeatures.wyvernLegs), - Tier.WYVERN, + DraconicTier.WYVERN, 6); // Wyvern Boots @@ -105,137 +104,130 @@ public static void init() { addTierUpRecipe( MetaItems.QUANTUM_BOOTS.getStackForm(), new ItemStack(DEFeatures.wyvernBoots), - Tier.WYVERN, + DraconicTier.WYVERN, 6); // Draconic Axe addTierUpRecipe( new ItemStack(DEFeatures.wyvernAxe), new ItemStack(DEFeatures.draconicAxe), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Pickaxe addTierUpRecipe( new ItemStack(DEFeatures.wyvernPick), new ItemStack(DEFeatures.draconicPick), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Shovel addTierUpRecipe( new ItemStack(DEFeatures.wyvernShovel), new ItemStack(DEFeatures.draconicShovel), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Sword addTierUpRecipe( new ItemStack(DEFeatures.wyvernSword), new ItemStack(DEFeatures.draconicSword), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Bow addTierUpRecipe( new ItemStack(DEFeatures.wyvernBow), new ItemStack(DEFeatures.draconicBow), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Staff of Power - GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_FAKE_RECIPES.recipeBuilder() - .catalyst(new GTRecipeItemInput(new ItemStack(DEFeatures.draconicPick)) - .setNBTMatchingCondition(NBTMatcher.ANY, NBTCondition.ANY)) + GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_RECIPES.recipeBuilder() + .catalyst(DEDARecipeHelper.inputWithAnyNBT(new ItemStack(DEFeatures.draconicPick))) .result(new ItemStack(DEFeatures.draconicStaffOfPower)) .input(plate, GTEMaterials.Draconium, 6) .inputNBT(DEFeatures.draconicAxe, NBTMatcher.ANY, NBTCondition.ANY) .inputNBT(DEFeatures.draconicShovel, NBTMatcher.ANY, NBTCondition.ANY) .inputNBT(DEFeatures.draconicSword, NBTMatcher.ANY, NBTCondition.ANY) .input(DEFeatures.draconicCore, 4) - .fluidInputs(GTEMaterials.Cryotheum.getFluid(32000)) - .fluidOutputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 8000)) - .duration(400).EUt(VA[GTEValues.dedaVoltageTier + 1]) + .fluidInputs(DEDARecipeHelper.cryotheum(DraconicTier.DRACONIC)) + .fluidOutputs(DEDARecipeHelper.pyrotheum(DraconicTier.DRACONIC)) + .duration(DEDAConstants.DURATION_DRACONIC).EUt(DEDARecipeHelper.voltage(DraconicTier.DRACONIC)) .buildAndRegister(); // Draconic Helm addTierUpRecipe( new ItemStack(DEFeatures.wyvernHelm), new ItemStack(DEFeatures.draconicHelm), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Chest addTierUpRecipe( new ItemStack(DEFeatures.wyvernChest), new ItemStack(DEFeatures.draconicChest), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Legs addTierUpRecipe( new ItemStack(DEFeatures.wyvernLegs), new ItemStack(DEFeatures.draconicLegs), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Draconic Boots addTierUpRecipe( new ItemStack(DEFeatures.wyvernBoots), new ItemStack(DEFeatures.draconicBoots), - Tier.DRACONIC); + DraconicTier.DRACONIC); // Chaotic Staff of Power addTierUpRecipe( new ItemStack(DEFeatures.draconicStaffOfPower), new ItemStack(DAFeatures.chaoticStaffOfPower), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); // Chaotic Bow addTierUpRecipe( new ItemStack(DEFeatures.draconicBow), new ItemStack(DAFeatures.chaoticBow), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); // Chaotic Helm addTierUpRecipe( new ItemStack(DEFeatures.draconicHelm), new ItemStack(DAFeatures.chaoticHelm), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); // Chaotic Chest addTierUpRecipe( new ItemStack(DEFeatures.draconicChest), new ItemStack(DAFeatures.chaoticChest), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); // Chaotic Leggings addTierUpRecipe( new ItemStack(DEFeatures.draconicLegs), new ItemStack(DAFeatures.chaoticLegs), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); // Chaotic Boots addTierUpRecipe( new ItemStack(DEFeatures.draconicBoots), new ItemStack(DAFeatures.chaoticBoots), - Tier.CHAOTIC); + DraconicTier.CHAOTIC); } - private static void addTierUpRecipe(ItemStack catalyst, ItemStack result, Tier tier) { + private static void addTierUpRecipe(ItemStack catalyst, ItemStack result, DraconicTier tier) { addTierUpRecipe(catalyst, result, tier, -1); } - private static void addTierUpRecipe(GTRecipeInput catalyst, ItemStack result, Tier tier) { + private static void addTierUpRecipe(GTRecipeInput catalyst, ItemStack result, DraconicTier tier) { addTierUpRecipe(catalyst, result, tier, -1); } - private static void addTierUpRecipe(ItemStack catalyst, ItemStack result, Tier tier, int plateAmount) { + private static void addTierUpRecipe(ItemStack catalyst, ItemStack result, DraconicTier tier, int plateAmount) { addTierUpRecipe( new GTRecipeItemInput(catalyst).setNBTMatchingCondition(NBTMatcher.ANY, NBTCondition.ANY), result, tier, plateAmount); } - private static void addTierUpRecipe(GTRecipeInput catalyst, ItemStack result, Tier tier, int plateAmount) { - RecipeMap recipeMap; - if (tier == Tier.CHAOTIC) { - recipeMap = GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_TIER_UP_FAKE_RECIPES; - } else { - recipeMap = GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_FAKE_RECIPES; - } - TierUpRecipeBuilder recipeBuilder = recipeMap.recipeBuilder(); + private static void addTierUpRecipe(GTRecipeInput catalyst, ItemStack result, DraconicTier tier, int plateAmount) { + TierUpRecipeBuilder recipeBuilder = GTEDraconicRecipeMaps.DRACONIC_FUSION_TIER_UP_RECIPES.recipeBuilder(); recipeBuilder.catalyst(catalyst).result(result); switch (tier) { @@ -243,31 +235,25 @@ private static void addTierUpRecipe(GTRecipeInput catalyst, ItemStack result, Ti .input(plate, GTEMaterials.Draconium, plateAmount) .input(DEFeatures.wyvernCore, 1) .input(DEFeatures.wyvernEnergyCore, 1) - .fluidInputs(GTEMaterials.Cryotheum.getFluid(16000)) - .fluidOutputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 4000)) - .duration(200).EUt(VA[GTEValues.dedaVoltageTier]); + .fluidInputs(DEDARecipeHelper.cryotheum(DraconicTier.WYVERN)) + .fluidOutputs(DEDARecipeHelper.pyrotheum(DraconicTier.WYVERN)) + .duration(DEDAConstants.DURATION_WYVERN).EUt(DEDARecipeHelper.voltage(DraconicTier.WYVERN)); case DRACONIC -> recipeBuilder .input(plate, GTEMaterials.AwakenedDraconium, 2) .input(DEFeatures.draconicCore, 4) .input(DEFeatures.draconicEnergyCore, 1) - .fluidInputs(GTEMaterials.Cryotheum.getFluid(32000)) - .fluidOutputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 8000)) - .duration(400).EUt(VA[GTEValues.dedaVoltageTier + 1]); + .fluidInputs(DEDARecipeHelper.cryotheum(DraconicTier.DRACONIC)) + .fluidOutputs(DEDARecipeHelper.pyrotheum(DraconicTier.DRACONIC)) + .duration(DEDAConstants.DURATION_DRACONIC).EUt(DEDARecipeHelper.voltage(DraconicTier.DRACONIC)); case CHAOTIC -> recipeBuilder .input(DEFeatures.chaosShard, 4, 0) .input(DEFeatures.infusedObsidian, 2) .input(DEFeatures.chaoticCore, 1) .input(DAFeatures.chaoticEnergyCore, 1) - .fluidInputs(GTEMaterials.Cryotheum.getFluid(48000)) - .fluidOutputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, 12000)) - .duration(600).EUt(VA[GTEValues.dedaVoltageTier + 2]); + .fluidInputs(DEDARecipeHelper.cryotheum(DraconicTier.CHAOTIC)) + .fluidOutputs(DEDARecipeHelper.pyrotheum(DraconicTier.CHAOTIC)) + .duration(DEDAConstants.DURATION_CHAOTIC).EUt(DEDARecipeHelper.voltage(DraconicTier.CHAOTIC)); } recipeBuilder.buildAndRegister(); } - - private enum Tier { - WYVERN, - DRACONIC, - CHAOTIC - } } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicUpgradeRecipe.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicUpgradeRecipe.java index d2c0c9e2..12c8ecc7 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicUpgradeRecipe.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipes/DraconicUpgradeRecipe.java @@ -11,7 +11,6 @@ import com.brandon3055.draconicevolution.api.itemupgrade.IUpgradableItem; import com.brandon3055.draconicevolution.items.ToolUpgrade; -import gregtech.api.recipes.RecipeMap; import gregtech.api.unification.material.Materials; import gregtech.api.unification.ore.OrePrefix; @@ -66,13 +65,8 @@ public static void init() { while (currentLevel < ToolUpgrade.NAME_MAX_LEVEL.get(upgradeName)) { if (item.getValidUpgrades(stack).contains(upgradeName) && item.getMaxUpgradeLevel(stack, upgradeName) >= currentLevel + 1) { - RecipeMap recipeMap; - if (currentLevel == 0 || currentLevel == 1) { - recipeMap = GTEDraconicRecipeMaps.DRACONIC_FUSION_UPGRADE_FAKE_RECIPES; - } else { - recipeMap = GTEDraconicRecipeMaps.AWAKENED_DRACONIC_FUSION_UPGRADE_FAKE_RECIPES; - } - UpgradeRecipeBuilder recipeBuilder = recipeMap.recipeBuilder(); + UpgradeRecipeBuilder recipeBuilder = GTEDraconicRecipeMaps.DRACONIC_FUSION_UPGRADE_RECIPES + .recipeBuilder(); recipeBuilder.catalyst(stack).upgradeName(upgradeName).level(currentLevel); switch (currentLevel) { diff --git a/src/main/java/com/github/gtexpert/core/mixins/gcym/AlloyBlastRecipeProducerMixin.java b/src/main/java/com/github/gtexpert/core/mixins/gcym/AlloyBlastRecipeProducerMixin.java index edfe3d48..030d70e6 100644 --- a/src/main/java/com/github/gtexpert/core/mixins/gcym/AlloyBlastRecipeProducerMixin.java +++ b/src/main/java/com/github/gtexpert/core/mixins/gcym/AlloyBlastRecipeProducerMixin.java @@ -1,7 +1,7 @@ package com.github.gtexpert.core.mixins.gcym; -import static com.github.gtexpert.core.integration.deda.recipes.DraconicMaterialsRecipe.ABFDurationMultiplier; -import static com.github.gtexpert.core.integration.deda.recipes.DraconicMaterialsRecipe.ABFPyrotheumAmount; +import static com.github.gtexpert.core.integration.deda.DEDAConstants.ABF_DURATION_MULTIPLIER; +import static com.github.gtexpert.core.integration.deda.DEDAConstants.ABF_PYROTHEUM_AMOUNT; import static gregtech.api.GTValues.*; import static gregtech.api.unification.material.info.MaterialFlags.*; import static gregtech.api.unification.ore.OrePrefix.*; @@ -62,8 +62,8 @@ private void buildRecipesMixin(@NotNull BlastProperty property, @NotNull Fluid m if (GTEValues.isModLoadedDEDA()) { RecipeBuilder builderPyrotheum = builder.copy(); builderPyrotheum.notConsumable(new IntCircuitIngredient(getPyrotheumCircuitNum(componentAmount))) - .fluidInputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, ABFPyrotheumAmount)) - .duration((int) (duration * 0.67 * ABFDurationMultiplier)) + .fluidInputs(GTEMaterials.Pyrotheum.getFluid(GCYMFluidStorageKeys.MOLTEN, ABF_PYROTHEUM_AMOUNT)) + .duration((int) (duration * 0.67 * ABF_DURATION_MULTIPLIER)) .buildAndRegister(); } } From 713cea370adc30dba29ab4f26dbc00ed801bedfa Mon Sep 17 00:00:00 2001 From: tier940 Date: Sun, 4 Jan 2026 12:14:59 +0900 Subject: [PATCH 2/3] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47df10d5..0f026138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # 2.5.7 - Mining Level and Tool Suitability Adjustments for Blocks Added via Chisel [#343](https://github.com/GTModpackTeam/GTExpert-Core/pull/343) +- DEDA Integration Refactoring [#344](https://github.com/GTModpackTeam/GTExpert-Core/pull/344) * * * From 184e76a8d290077484809912f2552a2b953a95f1 Mon Sep 17 00:00:00 2001 From: tier940 Date: Sun, 4 Jan 2026 12:18:37 +0900 Subject: [PATCH 3/3] Fix CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f026138..9dfb159d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.5.7 +# 2.6.0 - Mining Level and Tool Suitability Adjustments for Blocks Added via Chisel [#343](https://github.com/GTModpackTeam/GTExpert-Core/pull/343) - DEDA Integration Refactoring [#344](https://github.com/GTModpackTeam/GTExpert-Core/pull/344)