From 445ae50e8236e3f0dcc656030cc11ea629a49a22 Mon Sep 17 00:00:00 2001 From: tier940 Date: Tue, 20 Jan 2026 15:38:02 +0900 Subject: [PATCH 1/3] temp --- .../MultiblockRecipeLogicNoCache.java | 7 +- .../deda/provider/DEDAJEIProvider.java | 15 +- .../deda/recipemaps/DraconicRecipeUtils.java | 121 ++++++++++++ .../recipemaps/GTEDraconicRecipeMaps.java | 54 ++---- .../recipemaps/RecipeMapDraconicFusion.java | 180 ++---------------- .../recipemaps/RecipeMapDraconicTierUp.java | 43 +++++ .../recipemaps/RecipeMapDraconicUpgrade.java | 78 +++++++- 7 files changed, 294 insertions(+), 204 deletions(-) create mode 100644 src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/DraconicRecipeUtils.java create mode 100644 src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicTierUp.java diff --git a/src/main/java/com/github/gtexpert/core/api/capability/MultiblockRecipeLogicNoCache.java b/src/main/java/com/github/gtexpert/core/api/capability/MultiblockRecipeLogicNoCache.java index 2c92eab9..a023ec6f 100644 --- a/src/main/java/com/github/gtexpert/core/api/capability/MultiblockRecipeLogicNoCache.java +++ b/src/main/java/com/github/gtexpert/core/api/capability/MultiblockRecipeLogicNoCache.java @@ -3,12 +3,11 @@ import gregtech.api.capability.impl.MultiblockRecipeLogic; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; -import com.github.gtexpert.core.integration.deda.recipemaps.RecipeMapDraconicFusion; - /** * This recipe logic disables cache used for speeding up recipe check. - * The reason is we do some special things inside {@link RecipeMapDraconicFusion}, - * and reusing recipe causes item with incorrect NBT to be outputted. + * The reason is that Draconic Fusion recipes (TierUp and Upgrade) do special + * output processing based on input NBT, and reusing recipe causes items with + * incorrect NBT to be outputted. * Considering draconic fusion multi will not be spammed nor OCed to 1 tick, impact to TPS should be negligible. */ public class MultiblockRecipeLogicNoCache extends MultiblockRecipeLogic { 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 91c0a487..ee6ee99f 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,16 +19,27 @@ public class DEDAJEIProvider implements IModPlugin { @Override public void register(@NotNull IModRegistry registry) { if (GTEValues.isModLoadedDEDA()) { - String fusionCategory = GTValues.MODID + ":" + + // Fusion categories + String draconiumFusionCategory = GTValues.MODID + ":" + GTEDraconicRecipeMaps.DRACONIUM_FUSION_RECIPES.unlocalizedName; + String awakenedFusionCategory = GTValues.MODID + ":" + + GTEDraconicRecipeMaps.AWAKENED_DRACONIUM_FUSION_RECIPES.unlocalizedName; + + // Shared categories 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); + // Register Fusion categories + registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), + draconiumFusionCategory); + + // Register TierUp category registry.addRecipeCatalyst(DEDAMetaTileEntities.DRACONIUM_FUSION.getStackForm(), tierUpCategory); registry.addRecipeCatalyst(DEDAMetaTileEntities.AWAKENED_DRACONIUM_FUSION.getStackForm(), tierUpCategory); + + // Register Upgrade category 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/DraconicRecipeUtils.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/DraconicRecipeUtils.java new file mode 100644 index 00000000..15a7ab8c --- /dev/null +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/DraconicRecipeUtils.java @@ -0,0 +1,121 @@ +package com.github.gtexpert.core.integration.deda.recipemaps; + +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.Constants; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.brandon3055.brandonscore.utils.ItemNBTHelper; +import com.brandon3055.draconicevolution.api.fusioncrafting.IFusionRecipe; +import com.brandon3055.draconicevolution.api.fusioncrafting.SimpleFusionRecipe; +import com.brandon3055.draconicevolution.api.itemupgrade.FusionUpgradeRecipe; +import com.brandon3055.draconicevolution.api.itemupgrade.IUpgradableItem; +import com.brandon3055.draconicevolution.api.itemupgrade.UpgradeHelper; +import com.brandon3055.draconicevolution.items.ToolUpgrade; + +import gregtech.api.capability.FeCompat; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IElectricItem; +import gregtech.api.recipes.Recipe; + +import com.github.gtexpert.core.api.util.GTELog; + +import cofh.redstoneflux.api.IEnergyContainerItem; + +/** + * Utility methods shared between TierUp and Upgrade recipe maps. + */ +public final class DraconicRecipeUtils { + + private DraconicRecipeUtils() {} + + /** + * Applies default upgrade tags to upgradable items. + * This ensures consistent NBT state for recipe matching. + */ + public static void applyDefaultUpgradeTag(List inputs) { + for (ItemStack input : inputs) { + if (!(input.getItem() instanceof IUpgradableItem item)) continue; + for (String upgradeName : ToolUpgrade.NAME_TO_ID.keySet()) { + if (!item.getValidUpgrades(input).contains(upgradeName)) continue; + NBTTagCompound upgradeTag = input.getOrCreateSubCompound(UpgradeHelper.UPGRADE_TAG); + if (upgradeTag.hasKey(upgradeName, Constants.NBT.TAG_BYTE)) continue; + upgradeTag.setByte(upgradeName, (byte) 0); + } + } + } + + /** + * Sets up the output item for a TierUp or Upgrade recipe. + * Handles NBT copying and energy conversion. + */ + @Nullable + public static Recipe setupOutput(Recipe gtRecipe, List inputs, IFusionRecipe fusionRecipe) { + if (fusionRecipe == null) { + GTELog.logger.warn("Recipe found, but property not found"); + GTELog.logger.warn("Recipe: " + gtRecipe); + return null; + } + ItemStack catalyst = findCatalyst(inputs, fusionRecipe); + if (catalyst.isEmpty()) { + GTELog.logger.warn("Recipe found, but actual catalyst not found in the GT recipe"); + GTELog.logger.warn("Recipe: " + gtRecipe); + GTELog.logger.warn("Expected catalyst: " + fusionRecipe.getRecipeCatalyst()); + return null; + } + + ItemStack outputStack = fusionRecipe.getRecipeOutput(catalyst); + + // convert GTEU to FE + IElectricItem inputElectricItem = catalyst.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null); + if (inputElectricItem != null) { + long euCharge = inputElectricItem.getCharge(); + int feCharge = (int) Math.min(euCharge * FeCompat.ratio(false), Integer.MAX_VALUE); + if (outputStack.getItem() instanceof IEnergyContainerItem outputEnergyItem) { + ItemNBTHelper.setInteger(outputStack, "Energy", + Math.min(feCharge, outputEnergyItem.getMaxEnergyStored(outputStack))); + } + } + + Recipe retRecipe = gtRecipe.copy(); + retRecipe.getOutputs().clear(); // This assumes there's only 1 output + retRecipe.getOutputs().add(outputStack); + return retRecipe; + } + + @NotNull + public static ItemStack findCatalyst(List inputs, IFusionRecipe fusionRecipe) { + ItemStack expectedCatalyst = getCatalyst(fusionRecipe); + if (expectedCatalyst == null || expectedCatalyst.isEmpty()) { + return ItemStack.EMPTY; + } + for (ItemStack input : inputs) { + if (expectedCatalyst.getItem() == input.getItem() && + expectedCatalyst.getItemDamage() == input.getItemDamage() && fusionRecipe.isRecipeCatalyst(input)) { + return input; + } + } + return ItemStack.EMPTY; + } + + @Nullable + public static ItemStack getCatalyst(IFusionRecipe fusionRecipe) { + if (fusionRecipe instanceof SimpleFusionRecipe) { + return fusionRecipe.getRecipeCatalyst(); + } else if (fusionRecipe instanceof FusionUpgradeRecipe) { + List ingredients = ((FusionUpgradeRecipe) fusionRecipe).getRecipeIngredients(); + if (ingredients.isEmpty() || !(ingredients.get(0) instanceof ItemStack)) { + GTELog.logger.warn("Unknown ingredient: " + (ingredients.isEmpty() ? "empty" : ingredients.get(0))); + GTELog.logger.warn("Recipe: " + fusionRecipe); + return null; + } + return (ItemStack) ingredients.get(0); + } else { + throw new RuntimeException("Unknown type of IFusionRecipe: " + fusionRecipe.getClass().getName()); + } + } +} 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 03b0ce7b..d510f334 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 @@ -4,7 +4,6 @@ import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.builders.SimpleRecipeBuilder; -import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.core.sound.GTSoundEvents; import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeBuilder; @@ -18,47 +17,34 @@ @ZenRegister public class GTEDraconicRecipeMaps { - /** - * 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}. - */ @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); + public static final RecipeMapDraconicTierUp DRACONIC_FUSION_TIER_UP_RECIPES = new RecipeMapDraconicTierUp( + "draconic_fusion_tier_up", 6, 3, 3, 1, new TierUpRecipeBuilder(), false); - /** - * 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}. - */ @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); + public static final RecipeMapDraconicUpgrade DRACONIC_FUSION_UPGRADE_RECIPES = new RecipeMapDraconicUpgrade( + "draconic_fusion_upgrade", 6, 3, 3, 1, new UpgradeRecipeBuilder(), false); @ZenProperty public static final RecipeMap DRACONIUM_FUSION_RECIPES = new RecipeMapDraconicFusion( "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( - recipeBuilder -> GTEDraconicRecipeMaps.AWAKENED_DRACONIUM_FUSION_RECIPES - .recipeBuilder() - .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) - .fluidInputs(recipeBuilder.getFluidInputs()) - .outputs(recipeBuilder.getOutputs()) - .fluidOutputs(recipeBuilder.getFluidOutputs()) - .duration(recipeBuilder.getDuration()) - .EUt(recipeBuilder.getEUt()) - .buildAndRegister()); + DRACONIC_FUSION_TIER_UP_RECIPES, DRACONIC_FUSION_UPGRADE_RECIPES); @ZenProperty public static final RecipeMap AWAKENED_DRACONIUM_FUSION_RECIPES = new RecipeMapDraconicFusion( - "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); + "awakened_draconium_fusion", 6, 3, 3, 1, new SimpleRecipeBuilder(), false, + DRACONIC_FUSION_TIER_UP_RECIPES, DRACONIC_FUSION_UPGRADE_RECIPES); + + static { + DRACONIC_FUSION_TIER_UP_RECIPES + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL); + DRACONIC_FUSION_UPGRADE_RECIPES + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL); + DRACONIUM_FUSION_RECIPES + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) + .setSound(GTSoundEvents.ELECTROLYZER); + AWAKENED_DRACONIUM_FUSION_RECIPES + .setProgressBar(GuiTextures.PROGRESS_BAR_FUSION, ProgressWidget.MoveType.HORIZONTAL) + .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 7ff75ee3..cc455b2f 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 @@ -3,51 +3,31 @@ import java.util.List; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.Constants; import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.brandon3055.brandonscore.utils.ItemNBTHelper; -import com.brandon3055.draconicevolution.api.fusioncrafting.IFusionRecipe; -import com.brandon3055.draconicevolution.api.fusioncrafting.SimpleFusionRecipe; -import com.brandon3055.draconicevolution.api.itemupgrade.FusionUpgradeRecipe; -import com.brandon3055.draconicevolution.api.itemupgrade.IUpgradableItem; -import com.brandon3055.draconicevolution.api.itemupgrade.UpgradeHelper; -import com.brandon3055.draconicevolution.items.ToolUpgrade; - -import gregtech.api.capability.FeCompat; -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IElectricItem; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; 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.TierUpRecipeInfo; -import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeProperty; -import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeBuilder; -import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeInfo; -import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeProperty; - -import cofh.redstoneflux.api.IEnergyContainerItem; - +/** + * RecipeMap for Draconic Fusion machines. + * Holds Fusion recipes (via parent class) and delegates to TierUp and Upgrade RecipeMaps. + *

+ * Search order: Fusion (own recipes) → TierUp → Upgrade + */ 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(); + private final RecipeMapDraconicTierUp tierUpRecipeMap; + private final RecipeMapDraconicUpgrade upgradeRecipeMap; public RecipeMapDraconicFusion(@NotNull String unlocalizedName, int maxInputs, int maxOutputs, int maxFluidInputs, int maxFluidOutputs, @NotNull SimpleRecipeBuilder defaultRecipeBuilder, - boolean isHidden, RecipeMap tierUpRecipeMap, - RecipeMap upgradeRecipeMap) { + boolean isHidden, + RecipeMapDraconicTierUp tierUpRecipeMap, + RecipeMapDraconicUpgrade upgradeRecipeMap) { super(unlocalizedName, maxInputs, maxOutputs, maxFluidInputs, maxFluidOutputs, defaultRecipeBuilder, isHidden); this.tierUpRecipeMap = tierUpRecipeMap; this.upgradeRecipeMap = upgradeRecipeMap; @@ -56,141 +36,19 @@ public RecipeMapDraconicFusion(@NotNull String unlocalizedName, int maxInputs, i @Nullable @Override public Recipe findRecipe(long voltage, List inputs, List fluidInputs, boolean exactVoltage) { - Recipe superRecipe = super.findRecipe(voltage, inputs, fluidInputs, exactVoltage); - if (superRecipe != null) { - return superRecipe; + // 1. Check own Fusion recipes + Recipe fusionRecipe = super.findRecipe(voltage, inputs, fluidInputs, exactVoltage); + if (fusionRecipe != null) { + return fusionRecipe; } - applyDefaultUpgradeTag(inputs); - + // 2. Check TierUp recipes Recipe tierUpRecipe = tierUpRecipeMap.findRecipe(voltage, inputs, fluidInputs, exactVoltage); if (tierUpRecipe != null) { - TierUpRecipeInfo tierUpInfo = tierUpRecipe.getProperty(TierUpRecipeProperty.getInstance(), null); - return setupOutput(tierUpRecipe, inputs, tierUpInfo != null ? tierUpInfo.recipe() : null); - } - - // 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) { - UpgradeRecipeInfo upgradeInfo = upgradeRecipe.getProperty(UpgradeRecipeProperty.getInstance(), null); - return setupOutput(upgradeRecipe, inputs, upgradeInfo != null ? upgradeInfo.recipe() : 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 recipe; - } - } - return null; - } - - private void applyDefaultUpgradeTag(List inputs) { - for (ItemStack input : inputs) { - if (!(input.getItem() instanceof IUpgradableItem item)) continue; - for (String upgradeName : ToolUpgrade.NAME_TO_ID.keySet()) { - if (!item.getValidUpgrades(input).contains(upgradeName)) continue; - NBTTagCompound upgradeTag = input.getOrCreateSubCompound(UpgradeHelper.UPGRADE_TAG); - if (upgradeTag.hasKey(upgradeName, Constants.NBT.TAG_BYTE)) continue; - upgradeTag.setByte(upgradeName, (byte) 0); - } - } - } - - private Recipe setupOutput(Recipe gtRecipe, List inputs, IFusionRecipe fusionRecipe) { - if (fusionRecipe == null) { - GTELog.logger.warn("Recipe found, but property not found"); - GTELog.logger.warn("Recipe: " + gtRecipe); - return null; - } - ItemStack catalyst = findCatalyst(inputs, fusionRecipe); - if (catalyst.isEmpty()) { - GTELog.logger.warn("Recipe found, but actual catalyst not found in the GT recipe"); - GTELog.logger.warn("Recipe: " + gtRecipe); - GTELog.logger.warn("Expected catalyst: " + fusionRecipe.getRecipeCatalyst()); - return null; - } - - ItemStack outputStack = fusionRecipe.getRecipeOutput(catalyst); - - // convert GTEU to FE - IElectricItem inputElectricItem = catalyst.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null); - if (inputElectricItem != null) { - long euCharge = inputElectricItem.getCharge(); - int feCharge = (int) Math.min(euCharge * FeCompat.ratio(false), Integer.MAX_VALUE); - if (outputStack.getItem() instanceof IEnergyContainerItem outputEnergyItem) { - ItemNBTHelper.setInteger(outputStack, "Energy", - Math.min(feCharge, outputEnergyItem.getMaxEnergyStored(outputStack))); - } + return tierUpRecipe; } - Recipe retRecipe = gtRecipe.copy(); - retRecipe.getOutputs().clear(); // This assumes there's only 1 output - retRecipe.getOutputs().add(outputStack); - return retRecipe; - } - - @NotNull - private ItemStack findCatalyst(List inputs, IFusionRecipe fusionRecipe) { - ItemStack expectedCatalyst = getCatalyst(fusionRecipe); - if (expectedCatalyst == null || expectedCatalyst.isEmpty()) { - return ItemStack.EMPTY; - } - for (ItemStack input : inputs) { - if (expectedCatalyst.getItem() == input.getItem() && - expectedCatalyst.getItemDamage() == input.getItemDamage() && fusionRecipe.isRecipeCatalyst(input)) { - return input; - } - } - return ItemStack.EMPTY; - } - - @Nullable - private static ItemStack getCatalyst(IFusionRecipe fusionRecipe) { - if (fusionRecipe instanceof SimpleFusionRecipe) { - return fusionRecipe.getRecipeCatalyst(); - } else if (fusionRecipe instanceof FusionUpgradeRecipe) { - List ingredients = ((FusionUpgradeRecipe) fusionRecipe).getRecipeIngredients(); - if (ingredients.isEmpty() || !(ingredients.get(0) instanceof ItemStack)) { - GTELog.logger.warn("Unknown ingredient: " + (ingredients.isEmpty() ? "empty" : ingredients.get(0))); - GTELog.logger.warn("Recipe: " + fusionRecipe); - return null; - } - return (ItemStack) ingredients.get(0); - } else { - throw new RuntimeException("Unknown type of IFusionRecipe: " + fusionRecipe.getClass().getName()); - } + // 3. Check Upgrade recipes + return upgradeRecipeMap.findRecipe(voltage, inputs, fluidInputs, exactVoltage); } } diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicTierUp.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicTierUp.java new file mode 100644 index 00000000..f19bda83 --- /dev/null +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicTierUp.java @@ -0,0 +1,43 @@ +package com.github.gtexpert.core.integration.deda.recipemaps; + +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeMap; + +import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeBuilder; +import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeInfo; +import com.github.gtexpert.core.integration.deda.recipemaps.tierup.TierUpRecipeProperty; + +/** + * Recipe map for TierUp recipes (item tier upgrades like Wyvern → Draconic → Awakened). + * Handles special output processing for TierUp recipes. + */ +public class RecipeMapDraconicTierUp extends RecipeMap { + + public RecipeMapDraconicTierUp(@NotNull String unlocalizedName, int maxInputs, int maxOutputs, int maxFluidInputs, + int maxFluidOutputs, @NotNull TierUpRecipeBuilder defaultRecipeBuilder, + boolean isHidden) { + super(unlocalizedName, maxInputs, maxOutputs, maxFluidInputs, maxFluidOutputs, defaultRecipeBuilder, isHidden); + } + + @Nullable + @Override + public Recipe findRecipe(long voltage, List inputs, List fluidInputs, boolean exactVoltage) { + DraconicRecipeUtils.applyDefaultUpgradeTag(inputs); + + Recipe recipe = super.findRecipe(voltage, inputs, fluidInputs, exactVoltage); + if (recipe == null) { + return null; + } + + TierUpRecipeInfo tierUpInfo = recipe.getProperty(TierUpRecipeProperty.getInstance(), null); + return DraconicRecipeUtils.setupOutput(recipe, inputs, tierUpInfo != null ? tierUpInfo.recipe() : null); + } +} diff --git a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicUpgrade.java b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicUpgrade.java index 69b0d6f0..37f879a8 100644 --- a/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicUpgrade.java +++ b/src/main/java/com/github/gtexpert/core/integration/deda/recipemaps/RecipeMapDraconicUpgrade.java @@ -1,14 +1,86 @@ package com.github.gtexpert.core.integration.deda.recipemaps; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; -public class RecipeMapDraconicUpgrade> extends RecipeMap { +import com.github.gtexpert.core.integration.deda.DEDAConfigHolder; +import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeBuilder; +import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeInfo; +import com.github.gtexpert.core.integration.deda.recipemaps.upgrade.UpgradeRecipeProperty; + +/** + * Recipe map for Upgrade recipes (item stat upgrades like Attack Damage, Speed, etc.). + * Handles special output processing and caching for Upgrade recipes. + */ +public class RecipeMapDraconicUpgrade extends RecipeMap { + + /** Cache for upgrade recipe lookups - improves O(n) to O(m) where m << n */ + private final UpgradeRecipeCache upgradeCache = new UpgradeRecipeCache(); public RecipeMapDraconicUpgrade(@NotNull String unlocalizedName, int maxInputs, int maxOutputs, int maxFluidInputs, - int maxFluidOutputs, @NotNull R defaultRecipeBuilder, boolean isHidden) { + int maxFluidOutputs, @NotNull UpgradeRecipeBuilder defaultRecipeBuilder, + boolean isHidden) { super(unlocalizedName, maxInputs, maxOutputs, maxFluidInputs, maxFluidOutputs, defaultRecipeBuilder, isHidden); } + + @Nullable + @Override + public Recipe findRecipe(long voltage, List inputs, List fluidInputs, boolean exactVoltage) { + DraconicRecipeUtils.applyDefaultUpgradeTag(inputs); + + // 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 recipe = findUpgradeRecipe(voltage, inputs, fluidInputs); + if (recipe == null) { + return null; + } + + UpgradeRecipeInfo upgradeInfo = recipe.getProperty(UpgradeRecipeProperty.getInstance(), null); + return DraconicRecipeUtils.setupOutput(recipe, inputs, upgradeInfo != null ? upgradeInfo.recipe() : 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(this); + } + 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 : getRecipeList()) { + if (recipe.getEUt() <= voltage && recipe.matches(false, inputs, fluidInputs)) { + return recipe; + } + } + return null; + } } From 8a69b485a2bb8dc996b7ffef850cf73b5fb613cf Mon Sep 17 00:00:00 2001 From: tier940 Date: Tue, 20 Jan 2026 15:56:09 +0900 Subject: [PATCH 2/3] update --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f875325..53a10391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 2.6.4 +- Re: Improve the VOM UI [#351](https://github.com/GTModpackTeam/GTExpert-Core/pull/351) +- The AwakenedFusion category is hidden [#352](https://github.com/GTModpackTeam/GTExpert-Core/pull/352) + +* * * + # 2.6.3 - Re: Fix Disable Helmet AutoEat Mixin [#349](https://github.com/GTModpackTeam/GTExpert-Core/pull/349) - Improved VFP overclock efficiency with quadratic scaling [#350](https://github.com/GTModpackTeam/GTExpert-Core/pull/350) From f76df9a00d3c505bee418a68cba9d8b26aaf725d Mon Sep 17 00:00:00 2001 From: tier940 Date: Tue, 20 Jan 2026 17:09:05 +0900 Subject: [PATCH 3/3] fix --- {.gemnin => .gemini}/config.yaml | 0 {.gemnin => .gemini}/styleguide.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {.gemnin => .gemini}/config.yaml (100%) rename {.gemnin => .gemini}/styleguide.md (100%) diff --git a/.gemnin/config.yaml b/.gemini/config.yaml similarity index 100% rename from .gemnin/config.yaml rename to .gemini/config.yaml diff --git a/.gemnin/styleguide.md b/.gemini/styleguide.md similarity index 100% rename from .gemnin/styleguide.md rename to .gemini/styleguide.md