diff options
Diffstat (limited to 'src/main/java/tectech/recipe')
-rw-r--r-- | src/main/java/tectech/recipe/EyeOfHarmonyFrontend.java | 206 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/EyeOfHarmonyRecipe.java | 465 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/EyeOfHarmonyRecipeStorage.java | 186 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/GodforgeExoticFrontend.java | 82 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/GodforgePlasmaFrontend.java | 79 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/ResearchStationFrontend.java | 101 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/TTRecipeAdder.java | 251 | ||||
-rw-r--r-- | src/main/java/tectech/recipe/TecTechRecipeMaps.java | 78 |
8 files changed, 1448 insertions, 0 deletions
diff --git a/src/main/java/tectech/recipe/EyeOfHarmonyFrontend.java b/src/main/java/tectech/recipe/EyeOfHarmonyFrontend.java new file mode 100644 index 0000000000..4e1c40eb41 --- /dev/null +++ b/src/main/java/tectech/recipe/EyeOfHarmonyFrontend.java @@ -0,0 +1,206 @@ +package tectech.recipe; + +import static com.google.common.math.LongMath.pow; +import static gregtech.api.util.GTUtility.formatNumbers; +import static java.lang.Math.min; +import static net.minecraft.util.EnumChatFormatting.BOLD; +import static net.minecraft.util.EnumChatFormatting.DARK_RED; +import static net.minecraft.util.EnumChatFormatting.RESET; +import static net.minecraft.util.StatCollector.translateToLocal; +import static net.minecraft.util.StatCollector.translateToLocalFormatted; +import static tectech.util.CommonValues.EOH_TIER_FANCY_NAMES; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.math.Size; + +import appeng.util.ReadableNumberConverter; +import codechicken.nei.PositionedStack; +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GTLanguageManager; +import gregtech.api.util.MethodsReturnNonnullByDefault; +import gregtech.common.gui.modularui.UIHelper; +import gregtech.nei.GTNEIDefaultHandler; +import gregtech.nei.RecipeDisplayInfo; +import gregtech.nei.formatter.INEISpecialInfoFormatter; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class EyeOfHarmonyFrontend extends RecipeMapFrontend { + + private static final int xDirMaxCount = 9; + private static final int itemRows = 9, fluidRows = 2; + public static final int maxItemInputs = 1, maxItemOutputs = xDirMaxCount * itemRows, maxFluidInputs = 0, + maxFluidOutputs = xDirMaxCount * fluidRows; + private static final int yOrigin = 8; + private static final long TRILLION = pow(10, 12); + + public EyeOfHarmonyFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super( + uiPropertiesBuilder.logoPos(new Pos2d(8, yOrigin)), + neiPropertiesBuilder.recipeBackgroundSize(new Size(170, 117 + (itemRows + fluidRows - 4) * 18)) + .neiSpecialInfoFormatter(new EyeOfHarmonySpecialValueFormatter())); + } + + @Override + public List<Pos2d> getItemInputPositions(int itemInputCount) { + return UIHelper.getGridPositions(itemInputCount, 79, yOrigin, 1, 1); + } + + public static final int maxItemsToRender = 80; + + @Override + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return UIHelper.getGridPositions(min(itemOutputCount, maxItemsToRender + 1), 7, yOrigin + 36, xDirMaxCount, 12); + } + + @Override + public List<Pos2d> getFluidInputPositions(int fluidInputCount) { + return UIHelper.getGridPositions(fluidInputCount, 0, 0, 0, 0); + } + + @Override + public List<Pos2d> getFluidOutputPositions(int fluidOutputCount) { + return UIHelper.getGridPositions(fluidOutputCount, 7, yOrigin + 13 * 17 - 7 - 16, xDirMaxCount, 3); + } + + @Override + public List<String> handleNEIItemTooltip(ItemStack stack, List<String> currentTip, + GTNEIDefaultHandler.CachedDefaultRecipe neiCachedRecipe) { + super.handleNEIItemTooltip(stack, currentTip, neiCachedRecipe); + EyeOfHarmonyRecipe currentRecipe = (EyeOfHarmonyRecipe) neiCachedRecipe.mRecipe.mSpecialItems; + + // Draw tooltip on planet item. + if (stack.isItemEqual(currentRecipe.getRecipeTriggerItem())) { + currentTip.add( + EnumChatFormatting.GRAY + translateToLocalFormatted( + "tt.nei.eoh.total_items", + formatNumbers(currentRecipe.getSumOfItems()))); + return currentTip; + } + + // Draw tooltip on other items. + double percentage = currentRecipe.getItemStackToProbabilityMap() + .getOrDefault(stack, -1.0); + + if (percentage != -1.0) { + currentTip.add(EnumChatFormatting.GRAY + translateToLocalFormatted("tt.nei.eoh.solid_mass", percentage)); + currentTip.add( + EnumChatFormatting.GRAY + translateToLocalFormatted( + "tt.nei.eoh.item_count", + formatNumbers( + currentRecipe.getItemStackToTrueStackSizeMap() + .get(stack)))); + } + + return currentTip; + } + + @Override + public void drawNEIOverlays(GTNEIDefaultHandler.CachedDefaultRecipe neiCachedRecipe) { + EyeOfHarmonyRecipe EOHRecipe = (EyeOfHarmonyRecipe) neiCachedRecipe.mRecipe.mSpecialItems; + for (PositionedStack stack : neiCachedRecipe.mInputs) { + if (stack instanceof GTNEIDefaultHandler.FixedPositionedStack) { + if (stack.item.isItemEqual(EOHRecipe.getRecipeTriggerItem())) { + drawNEIOverlayText(translateToLocal("NC"), stack); + } + } + } + for (PositionedStack stack : neiCachedRecipe.mOutputs) { + if (stack instanceof GTNEIDefaultHandler.FixedPositionedStack) { + if (EOHRecipe.getItemStackToTrueStackSizeMap() + .containsKey(stack.item)) { + long stackSize = EOHRecipe.getItemStackToTrueStackSizeMap() + .get(stack.item); + String displayString; + if (stackSize > 9999) { + displayString = ReadableNumberConverter.INSTANCE.toWideReadableForm(stackSize); + } else { + displayString = String.valueOf(stackSize); + } + + drawNEIOverlayText(displayString, stack, 0xffffff, 0.5f, true, Alignment.BottomRight); + } + } + } + } + + private static class EyeOfHarmonySpecialValueFormatter implements INEISpecialInfoFormatter { + + @Override + public List<String> format(RecipeDisplayInfo recipeInfo) { + EyeOfHarmonyRecipe recipe = (EyeOfHarmonyRecipe) recipeInfo.recipe.mSpecialItems; + List<String> result = new ArrayList<>(); + + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.Hydrogen.In", "Hydrogen") + ": " + + formatNumbers(recipe.getHydrogenRequirement()) + + " L"); + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.Helium.In", "Helium") + ": " + + formatNumbers(recipe.getHydrogenRequirement()) + + " L"); + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.SpacetimeTier", "Spacetime Tier") + ": " + + EOH_TIER_FANCY_NAMES[(int) recipe.getSpacetimeCasingTierRequired()]); + + if (recipe.getEUOutput() < TRILLION) { + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.EU.Out", "EU Output") + ": " + + formatNumbers(recipe.getEUOutput()) + + " EU"); + } else { + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.EU.Out", "EU Output") + ": " + + ReadableNumberConverter.INSTANCE.toWideReadableForm(recipe.getEUOutput()) + + " EU"); + } + + if (recipe.getEUOutput() < TRILLION) { + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.EU.In", "EU Input") + ": " + + formatNumbers(recipe.getEUStartCost()) + + " EU"); + } else { + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.EU.In", "EU Input") + ": " + + ReadableNumberConverter.INSTANCE.toWideReadableForm(recipe.getEUStartCost()) + + " EU"); + } + + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.BaseRecipeChance", "Base Recipe Chance") + ": " + + formatNumbers(100 * recipe.getBaseRecipeSuccessChance()) + + "%"); + result.add( + GTLanguageManager.addStringLocalization("EOH.Recipe.RecipeEnergyEfficiency", "Recipe Energy Efficiency") + + ": " + + formatNumbers(100 * recipe.getRecipeEnergyEfficiency()) + + "%"); + + if (recipe.getOutputItems() + .size() > maxItemsToRender) { + result.add( + "" + DARK_RED + + BOLD + + GTLanguageManager.addStringLocalization("EOH.Recipe.Warning.0", "Warning") + + RESET + + ": " + + GTLanguageManager.addStringLocalization("EOH.Recipe.Warning.1", "Not all items displayed.")); + } + + return result; + } + } +} diff --git a/src/main/java/tectech/recipe/EyeOfHarmonyRecipe.java b/src/main/java/tectech/recipe/EyeOfHarmonyRecipe.java new file mode 100644 index 0000000000..90acd63048 --- /dev/null +++ b/src/main/java/tectech/recipe/EyeOfHarmonyRecipe.java @@ -0,0 +1,465 @@ +package tectech.recipe; + +import static com.google.common.math.IntMath.pow; +import static gregtech.api.GregTechAPI.getUnificatedOreDictStack; +import static gregtech.api.enums.Mods.NewHorizonsCoreMod; +import static gregtech.api.util.GTModHandler.getModItem; +import static gregtech.api.util.GTUtility.getPlasmaFuelValueInEUPerLiterFromMaterial; +import static java.lang.Math.min; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.apache.commons.lang3.tuple.Pair; + +import gnu.trove.map.TMap; +import gnu.trove.map.hash.TCustomHashMap; +import gnu.trove.strategy.HashingStrategy; +import gregtech.api.enums.Materials; +import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.util.GTOreDictUnificator; +import gtneioreplugin.plugin.block.BlockDimensionDisplay; +import gtneioreplugin.util.GT5OreLayerHelper; +import gtneioreplugin.util.GT5OreSmallHelper; +import tectech.util.FluidStackLong; +import tectech.util.ItemStackLong; + +@SuppressWarnings("SpellCheckingInspection") +public class EyeOfHarmonyRecipe { + + static final FluidStackLong[] SPECIAL_FLUIDS = new FluidStackLong[] { + new FluidStackLong(MaterialsUEVplus.WhiteDwarfMatter.getMolten(1_152), 1_152), + new FluidStackLong(MaterialsUEVplus.WhiteDwarfMatter.getMolten(1_152), 1_152), + new FluidStackLong(MaterialsUEVplus.WhiteDwarfMatter.getMolten(4_608), 4_608), + new FluidStackLong(MaterialsUEVplus.WhiteDwarfMatter.getMolten(18_432), 18_432), + new FluidStackLong(MaterialsUEVplus.BlackDwarfMatter.getMolten(1_152), 1_152), + new FluidStackLong(MaterialsUEVplus.BlackDwarfMatter.getMolten(4_608), 4_608), + new FluidStackLong(MaterialsUEVplus.BlackDwarfMatter.getMolten(18_432), 18_432), + new FluidStackLong(MaterialsUEVplus.Universium.getMolten(1_152), 1_152), + new FluidStackLong(MaterialsUEVplus.Universium.getMolten(4_608), 4_608), + new FluidStackLong(MaterialsUEVplus.Universium.getMolten(18_432), 18_432) }; + + HashingStrategy<ItemStack> itemStackHashingStrategy = new HashingStrategy<>() { + + private static final long serialVersionUID = -3966004160368229212L; + + @Override + public int computeHashCode(ItemStack stack) { + // Not really sure how this works or if it is "unique enough". + int result = stack.getItem() + .hashCode(); + result = 31 * result + stack.getItemDamage(); + return result; + } + + @Override + public boolean equals(ItemStack item1, ItemStack item2) { + return item1.getUnlocalizedName() + .equals(item2.getUnlocalizedName()); + } + }; + + private final TMap<ItemStack, Double> itemStackToProbabilityMap = new TCustomHashMap<>(itemStackHashingStrategy); + private final TMap<ItemStack, Long> itemStackToTrueStackSizeMap = new TCustomHashMap<>(itemStackHashingStrategy); + + private final ArrayList<ItemStackLong> outputItems; + private final ArrayList<FluidStackLong> outputFluids; + + private final long hydrogenRequirement; + private final long heliumRequirement; + + private final long euOutput; + private final long euStartCost; + + private final double baseSuccessChance; + + private final long spacetimeCasingTierRequired; + + private final long miningTimeSeconds; + + private final double recipeEnergyEfficiency; + + private final ItemStack recipeTriggerItem; + + private final long sumOfItems; + private final long rocketTier; + + public TMap<ItemStack, Double> getItemStackToProbabilityMap() { + return itemStackToProbabilityMap; + } + + public TMap<ItemStack, Long> getItemStackToTrueStackSizeMap() { + return itemStackToTrueStackSizeMap; + } + + public double getRecipeEnergyEfficiency() { + return recipeEnergyEfficiency; + } + + @SuppressWarnings("FieldCanBeLocal") + private final long standardRecipeEUOutPerTick = 100 * EyeOfHarmonyRecipeStorage.BILLION; + + public long getSumOfItems() { + return sumOfItems; + } + + public long getRocketTier() { + return rocketTier; + } + + public EyeOfHarmonyRecipe(final ArrayList<Pair<Materials, Long>> materialList, final BlockDimensionDisplay block, + final double recipeEnergyEfficiency, final long hydrogenRequirement, final long heliumRequirement, + final long miningTimeSeconds, final long rocketTierOfRecipe, final double baseSuccessChance) { + + this.rocketTier = rocketTierOfRecipe; + this.spacetimeCasingTierRequired = min(8, rocketTierOfRecipe); + + this.recipeTriggerItem = new ItemStack(block); + + this.outputItems = validDustGenerator(materialList); + + this.sumOfItems = this.outputItems.stream() + .map(ItemStackLong::getStackSize) + .reduce(0L, Long::sum); + + this.outputItems.add(new ItemStackLong(getStoneDustType(block.getDimension()), this.sumOfItems * 3L)); + this.outputItems.sort(Comparator.comparingLong(ItemStackLong::getStackSize)); + Collections.reverse(this.outputItems); + + for (ItemStackLong itemStackLong : outputItems) { + double stackSize = (double) itemStackLong.getStackSize(); + double probability = Math.round(100_000 * stackSize / sumOfItems) / 1000.0; + + itemStackToProbabilityMap.put(itemStackLong.itemStack, probability); + itemStackToTrueStackSizeMap.put(itemStackLong.itemStack, itemStackLong.stackSize); + } + // End item processing. + + // --- Fluid handling --- + ArrayList<FluidStackLong> fluidStackLongArrayList = new ArrayList<>(); + + int plasmaAmount = (int) ((this.spacetimeCasingTierRequired + 1) * 8_000_000L); + + // If DeepDark then it should output all plasmas involved in making exotic catalyst. + if (rocketTier == 9) { + for (Materials material : VALID_PLASMAS) { + fluidStackLongArrayList.add(new FluidStackLong(material.getPlasma(plasmaAmount), plasmaAmount)); + } + } else { + // --- Output and process fluids of the recipe. + ArrayList<FluidStack> fluidStackArrayList = new ArrayList<>(validPlasmaGenerator(materialList)); + for (FluidStack fluidStack : fluidStackArrayList) { + fluidStack = new FluidStack(fluidStack, plasmaAmount); + fluidStackLongArrayList.add(new FluidStackLong(fluidStack, plasmaAmount)); + } + } + + // Add a bonus fluid of compressed star matter. + fluidStackLongArrayList.add( + new FluidStackLong( + MaterialsUEVplus.RawStarMatter.getFluid((this.spacetimeCasingTierRequired + 1) * 100_000), + (this.spacetimeCasingTierRequired + 1) * 100_000)); + + // Tier 0 & 1 - 576 White + // Tier 2 - 2304 White + // Tier 3 - 9216 White + + // Tier 4 - 576 Black + // Tier 5 - 2304 Black + // Tier 6 - 9216 Black + + // Tier 7 - 576 Universium + // Tier 8 - 2304 Universium + // Tier 9 - 9216 Universium + int spacetimeTier = (int) rocketTierOfRecipe; + if (spacetimeTier == 0 || spacetimeTier == 9) { + spacetimeTier -= 1; + } + fluidStackLongArrayList.add(SPECIAL_FLUIDS[spacetimeTier + 1]); + + outputFluids = fluidStackLongArrayList; + // --- End fluid handling ---. + + this.hydrogenRequirement = hydrogenRequirement; + this.heliumRequirement = heliumRequirement; + + this.baseSuccessChance = baseSuccessChance; + + this.miningTimeSeconds = miningTimeSeconds; + this.recipeEnergyEfficiency = recipeEnergyEfficiency; + + long plasmaEU = plasmaCostCalculator(outputFluids); + long VM3EU = miningTimeSeconds * pow(2, 19) * 20; + this.euStartCost = (plasmaEU + VM3EU + standardRecipeEUOutPerTick * 20 * miningTimeSeconds); + this.euOutput = (long) (euStartCost * recipeEnergyEfficiency); + } + + private ItemStack getStoneDustType(String key) { + ItemStack placeholder = GTOreDictUnificator.get(OrePrefixes.dust, Materials.Stone, 1); + return switch (key) { + case "Ne" -> GTOreDictUnificator.get(OrePrefixes.dust, Materials.Netherrack, 1); + case "ED", "VA", "EA" -> GTOreDictUnificator.get(OrePrefixes.dust, Materials.Endstone, 1); + case "Mo" -> getModItem(NewHorizonsCoreMod.ID, "item.MoonStoneDust", 1, placeholder); + case "De" -> getModItem(NewHorizonsCoreMod.ID, "item.DeimosStoneDust", 1, placeholder); + case "Ma" -> getModItem(NewHorizonsCoreMod.ID, "item.MarsStoneDust", 1, placeholder); + case "Ph" -> getModItem(NewHorizonsCoreMod.ID, "item.PhobosStoneDust", 1, placeholder); + case "As", "KB" -> getModItem(NewHorizonsCoreMod.ID, "item.AsteroidsStoneDust", 1, placeholder); + case "Ca" -> getModItem(NewHorizonsCoreMod.ID, "item.CallistoStoneDust", 1, placeholder); + case "Ce" -> getModItem(NewHorizonsCoreMod.ID, "item.CeresStoneDust", 1, placeholder); + case "Eu" -> getModItem(NewHorizonsCoreMod.ID, "item.EuropaStoneDust", 1, placeholder); + case "Ga" -> getModItem(NewHorizonsCoreMod.ID, "item.GanymedeStoneDust", 1, placeholder); + case "Io" -> getModItem(NewHorizonsCoreMod.ID, "item.IoStoneDust", 1, placeholder); + case "Me" -> getModItem(NewHorizonsCoreMod.ID, "item.MercuryStoneDust", 1, placeholder); + case "Ve" -> getModItem(NewHorizonsCoreMod.ID, "item.VenusStoneDust", 1, placeholder); + case "En" -> getModItem(NewHorizonsCoreMod.ID, "item.EnceladusStoneDust", 1, placeholder); + case "Mi" -> getModItem(NewHorizonsCoreMod.ID, "item.MirandaStoneDust", 1, placeholder); + case "Ob" -> getModItem(NewHorizonsCoreMod.ID, "item.OberonStoneDust", 1, placeholder); + case "Ti" -> getModItem(NewHorizonsCoreMod.ID, "item.TitanStoneDust", 1, placeholder); + case "Pr" -> getModItem(NewHorizonsCoreMod.ID, "item.ProteusStoneDust", 1, placeholder); + case "Tr" -> getModItem(NewHorizonsCoreMod.ID, "item.TritonStoneDust", 1, placeholder); + case "Ha" -> getModItem(NewHorizonsCoreMod.ID, "item.HaumeaStoneDust", 1, placeholder); + case "MM" -> getModItem(NewHorizonsCoreMod.ID, "item.MakeMakeStoneDust", 1, placeholder); + case "Pl" -> getModItem(NewHorizonsCoreMod.ID, "item.PlutoStoneDust", 1, placeholder); + case "BE" -> getModItem(NewHorizonsCoreMod.ID, "item.BarnardaEStoneDust", 1, placeholder); + case "BF" -> getModItem(NewHorizonsCoreMod.ID, "item.BarnardaFStoneDust", 1, placeholder); + case "CB" -> getModItem(NewHorizonsCoreMod.ID, "item.CentauriAStoneDust", 1, placeholder); + case "TE" -> getModItem(NewHorizonsCoreMod.ID, "item.TCetiEStoneDust", 1, placeholder); + case "VB" -> getModItem(NewHorizonsCoreMod.ID, "item.VegaBStoneDust", 1, placeholder); + default -> placeholder; + }; + } + + public EyeOfHarmonyRecipe(final GT5OreLayerHelper.NormalOreDimensionWrapper normalOreDimensionWrapper, + final GT5OreSmallHelper.SmallOreDimensionWrapper smallOreDimensionWrapper, final BlockDimensionDisplay block, + final double recipeEnergyEfficiency, final long hydrogenRequirement, final long heliumRequirement, + final long miningTimeSeconds, final long spacetimeCasingTierRequired, final double baseSuccessChance) { + + // Process recipes output items. + // 6 * 64 = 6 stacks/second for VM tier 3 + Og gas. + this( + processDimension(normalOreDimensionWrapper, smallOreDimensionWrapper, miningTimeSeconds), + block, + recipeEnergyEfficiency, + hydrogenRequirement, + heliumRequirement, + miningTimeSeconds, + spacetimeCasingTierRequired, + baseSuccessChance); + } + + // Return clone of list. Deep copy. Maybe a better way to do this? + public ArrayList<ItemStackLong> getOutputItems() { + ArrayList<ItemStackLong> copyOutputList = new ArrayList<>(); + for (ItemStackLong itemStackLong : outputItems) { + copyOutputList.add(new ItemStackLong(itemStackLong)); + } + + return copyOutputList; + } + + // Deep copy. + public ArrayList<FluidStackLong> getOutputFluids() { + ArrayList<FluidStackLong> copyOutputList = new ArrayList<>(); + + for (FluidStackLong fluidStackLong : outputFluids) { + copyOutputList.add(new FluidStackLong(fluidStackLong)); + } + + return copyOutputList; + } + + public long getHydrogenRequirement() { + return hydrogenRequirement; + } + + public long getHeliumRequirement() { + return heliumRequirement; + } + + public long getEUOutput() { + return euOutput; + } + + public long getEUStartCost() { + return euStartCost; + } + + public long getRecipeTimeInTicks() { + return miningTimeSeconds * 20; + } + + public double getBaseRecipeSuccessChance() { + return baseSuccessChance; + } + + public long getSpacetimeCasingTierRequired() { + return spacetimeCasingTierRequired; + } + + public ItemStack getRecipeTriggerItem() { + return recipeTriggerItem; + } + + private static final double PRIMARY_MULTIPLIER = (0.1 + 1.0 / 9.0); // Byproduct from macerating/washing chance. + private static final double SECONDARY_MULTIPLIER = (1.0 / 9.0); // Thermal centrifuge byproduct chance. + private static final double TERTIARY_MULTIPLIER = (0.1); // Macerating thermal centrifuged byproduct chance. + private static final double QUATERNARY_MULTIPLIER = (0.7); // Mercury/chem bath processing chance. + + private static final double[] ORE_MULTIPLIER = { PRIMARY_MULTIPLIER, SECONDARY_MULTIPLIER, TERTIARY_MULTIPLIER, + QUATERNARY_MULTIPLIER }; + + public static class HashMapHelper extends HashMap<Materials, Double> { + + private static final long serialVersionUID = 2297018142561480614L; + + void add(Materials material, double value) { + + // If key already exists. + if (this.containsKey(material)) { + this.put(material, value + this.get(material)); + return; + } + + // Otherwise, add value to hashmap entry. + this.put(material, value); + } + } + + public static void processHelper(HashMapHelper outputMap, Materials material, double mainMultiplier, + double probability) { + if (material == null) return; + outputMap.add(material.mDirectSmelting, (material.mOreMultiplier * 2) * mainMultiplier * probability); + + int index = 0; + for (Materials byProductMaterial : material.mOreByProducts) { + outputMap + .add(byProductMaterial.mDirectSmelting, mainMultiplier * (ORE_MULTIPLIER[index++] * 2) * probability); + } + } + + private static ArrayList<Pair<Materials, Long>> processDimension( + GT5OreLayerHelper.NormalOreDimensionWrapper normalOreDimWrapper, + GT5OreSmallHelper.SmallOreDimensionWrapper smallOreDimWrapper, long timeInSeconds) { + HashMapHelper outputMap = new HashMapHelper(); + + double mainMultiplier = timeInSeconds * 384.0; + + if (normalOreDimWrapper != null) { + normalOreDimWrapper.oreVeinToProbabilityInDimension.forEach((veinInfo, probability) -> { + processHelper(outputMap, veinInfo.mPrimaryVeinMaterial, mainMultiplier, probability); + processHelper(outputMap, veinInfo.mSecondaryMaterial, mainMultiplier, probability); + // 8.0 to replicate void miner getDropsVanillaVeins method yields. + processHelper(outputMap, veinInfo.mBetweenMaterial, mainMultiplier / 8.0, probability); + processHelper(outputMap, veinInfo.mSporadicMaterial, mainMultiplier / 8.0, probability); + }); + } + + // Iterate over small ores in dimension and add them, kinda hacky but works and is close enough. + if (smallOreDimWrapper != null) { + smallOreDimWrapper.oreVeinToProbabilityInDimension.forEach( + (veinInfo, + probability) -> processHelper(outputMap, veinInfo.getOreMaterial(), mainMultiplier, probability)); + } + + ArrayList<Pair<Materials, Long>> outputList = new ArrayList<>(); + + outputMap.forEach((material, quantity) -> outputList.add(Pair.of(material, (long) Math.floor(quantity)))); + + return outputList; + } + + private static ArrayList<FluidStack> validPlasmaGenerator(final List<Pair<Materials, Long>> planetList) { + + ArrayList<FluidStack> plasmaList = new ArrayList<>(); + + for (Pair<Materials, Long> pair : planetList) { + if (VALID_PLASMAS.contains(pair.getLeft())) { + plasmaList.add( + pair.getLeft() + .getPlasma(1)); + } + } + + return plasmaList; + } + + private static ArrayList<ItemStackLong> validDustGenerator(final ArrayList<Pair<Materials, Long>> planetList) { + + ArrayList<ItemStackLong> dustList = new ArrayList<>(); + + for (Pair<Materials, Long> pair : planetList) { + ItemStack dust = getUnificatedOreDictStack( + pair.getLeft() + .getDust(1)); + if (dust != null) { + dustList.add(new ItemStackLong(dust, pair.getRight())); + } + } + return dustList; + } + + private static long plasmaCostCalculator(ArrayList<FluidStackLong> plasmas) { + long total = 0; + + for (FluidStackLong plasma : plasmas) { + FluidStack plasmaFluid = plasma.getRegularFluidStack(plasma, 1); + try { + String plasmaName = plasmaFluid.getFluid() + .getUnlocalizedName(); + total += plasmaEnergyMap.getOrDefault(plasmaName, 0L) * plasma.amount; + } catch (Exception e) { + e.printStackTrace(); + } + } + + return (long) (total * getMaxPlasmaTurbineEfficiency()); + } + + private static double getMaxPlasmaTurbineEfficiency() { + // I hate Shirabon. + return 3.85; + } + + private static final List<Materials> VALID_PLASMAS = Stream + .of( + Materials.Helium, + Materials.Iron, + Materials.Calcium, + Materials.Niobium, + Materials.Nitrogen, + Materials.Zinc, + Materials.Silver, + Materials.Titanium, + Materials.Radon, + Materials.Nickel, + Materials.Boron, + Materials.Sulfur, + Materials.Americium, + Materials.Bismuth, + Materials.Oxygen, + Materials.Tin) + .collect(Collectors.toList()); + + private static final HashMap<String, Long> plasmaEnergyMap = new HashMap<>() { + + private static final long serialVersionUID = 7933945171103801933L; + + { + VALID_PLASMAS.forEach( + (material -> put( + material.getPlasma(1) + .getFluid() + .getUnlocalizedName(), + (long) (getPlasmaFuelValueInEUPerLiterFromMaterial(material) * getMaxPlasmaTurbineEfficiency())))); + } + }; +} diff --git a/src/main/java/tectech/recipe/EyeOfHarmonyRecipeStorage.java b/src/main/java/tectech/recipe/EyeOfHarmonyRecipeStorage.java new file mode 100644 index 0000000000..30671dc919 --- /dev/null +++ b/src/main/java/tectech/recipe/EyeOfHarmonyRecipeStorage.java @@ -0,0 +1,186 @@ +package tectech.recipe; + +import static java.lang.Math.pow; +import static tectech.recipe.EyeOfHarmonyRecipe.processHelper; +import static tectech.recipe.TecTechRecipeMaps.eyeOfHarmonyRecipes; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.math.LongMath; + +import gregtech.api.enums.GTValues; +import gregtech.api.enums.Materials; +import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.util.GTOreDictUnificator; +import gtneioreplugin.plugin.block.BlockDimensionDisplay; +import gtneioreplugin.plugin.block.ModBlocks; +import gtneioreplugin.util.DimensionHelper; +import gtneioreplugin.util.GT5OreLayerHelper; +import gtneioreplugin.util.GT5OreSmallHelper; +import tectech.util.FluidStackLong; +import tectech.util.ItemStackLong; + +public class EyeOfHarmonyRecipeStorage { + + public static final long BILLION = LongMath.pow(10, 9); + private static final double CHANCE_DECREASE_PER_DIMENSION = 0.05; + + // Map is unique so this is fine. + HashMap<Block, String> blocksMapInverted = new HashMap<>() { + + private static final long serialVersionUID = -1634011860327553337L; + + { + ModBlocks.blocks.forEach((dimString, dimBlock) -> { put(dimBlock, dimString); }); + } + }; + + private final HashMap<String, EyeOfHarmonyRecipe> recipeHashMap = new HashMap<String, EyeOfHarmonyRecipe>() { + + private static final long serialVersionUID = -3501819612517400500L; + + { + for (String dimAbbreviation : DimensionHelper.DimNameDisplayed) { + BlockDimensionDisplay blockDimensionDisplay = (BlockDimensionDisplay) ModBlocks.blocks + .get(dimAbbreviation); + + if (dimAbbreviation.equals("DD")) { + specialDeepDarkRecipe(this, blockDimensionDisplay); + } else { + + GT5OreLayerHelper.NormalOreDimensionWrapper normalOre = GT5OreLayerHelper.dimToOreWrapper + .getOrDefault(dimAbbreviation, null); + GT5OreSmallHelper.SmallOreDimensionWrapper smallOre = GT5OreSmallHelper.dimToSmallOreWrapper + .getOrDefault(dimAbbreviation, null); + if (normalOre == null && smallOre == null) { + // No ores are generated in this dimension. Fail silently. + continue; + } + + long spacetimeTier = blockDimensionDisplay.getDimensionRocketTier(); + if (spacetimeTier == 0) { + spacetimeTier += 1; + } + + put( + dimAbbreviation, + new EyeOfHarmonyRecipe( + normalOre, + smallOre, + blockDimensionDisplay, + 0.6 + blockDimensionDisplay.getDimensionRocketTier() / 10.0, + BILLION * (blockDimensionDisplay.getDimensionRocketTier() + 1), + BILLION * (blockDimensionDisplay.getDimensionRocketTier() + 1), + timeCalculator(blockDimensionDisplay.getDimensionRocketTier()), + spacetimeTier - 1, + 1.0 - CHANCE_DECREASE_PER_DIMENSION * blockDimensionDisplay.getDimensionRocketTier())); + } + } + } + }; + + public EyeOfHarmonyRecipe recipeLookUp(final ItemStack aStack) { + String dimAbbreviation = blocksMapInverted.get(Block.getBlockFromItem(aStack.getItem())); + return recipeHashMap.get(dimAbbreviation); + } + + public EyeOfHarmonyRecipeStorage() { + + for (EyeOfHarmonyRecipe recipe : recipeHashMap.values()) { + + ArrayList<ItemStack> outputItems = new ArrayList<>(); + for (ItemStackLong itemStackLong : recipe.getOutputItems()) { + outputItems.add(itemStackLong.itemStack); + } + + ArrayList<FluidStack> outputFluids = new ArrayList<>(); + for (FluidStackLong fluidStackLong : recipe.getOutputFluids()) { + outputFluids.add(fluidStackLong.fluidStack); + } + + ItemStack planetItem = recipe.getRecipeTriggerItem() + .copy(); + planetItem.stackSize = 0; + + GTValues.RA.stdBuilder() + .itemInputs(planetItem) + .itemOutputs(outputItems.toArray(new ItemStack[0])) + .fluidInputs( + Materials.Hydrogen.getGas(0), + Materials.Helium.getGas(0), + MaterialsUEVplus.RawStarMatter.getFluid(0)) + .fluidOutputs(outputFluids.toArray(new FluidStack[0])) + .duration(recipe.getRecipeTimeInTicks()) + .eut(0) + .special(recipe) + .noOptimize() + .addTo(eyeOfHarmonyRecipes); + } + } + + private void specialDeepDarkRecipe(final HashMap<String, EyeOfHarmonyRecipe> hashMap, + final BlockDimensionDisplay planetItem) { + + HashSet<Materials> validMaterialSet = new HashSet<>(); + + for (Materials material : Materials.values()) { + + ItemStack normalOre = GTOreDictUnificator.get(OrePrefixes.ore, material, 1); + + if ((normalOre != null)) { + validMaterialSet.add(material); + } + + ItemStack smallOre = GTOreDictUnificator.get(OrePrefixes.oreSmall, material, 1); + + if ((smallOre != null)) { + validMaterialSet.add(material); + } + } + + ArrayList<Materials> validMaterialList = new ArrayList<>(validMaterialSet); + + long rocketTier = 9; + + hashMap.put( + "DD", + new EyeOfHarmonyRecipe( + processDD(validMaterialList), + planetItem, + 0.6 + rocketTier / 10.0, + BILLION * (rocketTier + 1), + BILLION * (rocketTier + 1), + timeCalculator(rocketTier), + rocketTier, // -1 so that we avoid out of bounds exception on NEI render. + 1.0 - rocketTier * CHANCE_DECREASE_PER_DIMENSION)); + } + + private static long timeCalculator(final long rocketTier) { + return (long) (18_000L * pow(1.4, rocketTier)); + } + + private ArrayList<Pair<Materials, Long>> processDD(final ArrayList<Materials> validMaterialList) { + EyeOfHarmonyRecipe.HashMapHelper outputMap = new EyeOfHarmonyRecipe.HashMapHelper(); + + // 10 from rocketTier + 1, 6 * 64 = VM3 + Og, 1.4 = time increase per tier. + double mainMultiplier = (timeCalculator(10) * (6 * 64)); + double probability = 1.0 / validMaterialList.size(); + + validMaterialList.forEach((material) -> { processHelper(outputMap, material, mainMultiplier, probability); }); + + ArrayList<Pair<Materials, Long>> outputList = new ArrayList<>(); + + outputMap.forEach((material, quantity) -> outputList.add(Pair.of(material, (long) Math.floor(quantity)))); + + return outputList; + } +} diff --git a/src/main/java/tectech/recipe/GodforgeExoticFrontend.java b/src/main/java/tectech/recipe/GodforgeExoticFrontend.java new file mode 100644 index 0000000000..cb19f8862d --- /dev/null +++ b/src/main/java/tectech/recipe/GodforgeExoticFrontend.java @@ -0,0 +1,82 @@ +package tectech.recipe; + +import static gregtech.api.util.GTUtility.trans; +import static tectech.loader.recipe.Godforge.magmatterItemsForNEI; +import static tectech.loader.recipe.Godforge.magmatterSpaceFluidItemsForNEI; +import static tectech.loader.recipe.Godforge.magmatterTimeFluidItemsForNEI; +import static tectech.loader.recipe.Godforge.quarkGluonFluidItemsForNEI; +import static tectech.loader.recipe.Godforge.quarkGluonItemsForNEI; + +import java.util.Collections; +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; + +import codechicken.nei.PositionedStack; +import gregtech.api.enums.MaterialsUEVplus; +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MethodsReturnNonnullByDefault; +import gregtech.nei.GTNEIDefaultHandler; +import gregtech.nei.RecipeDisplayInfo; +import tectech.thing.gui.TecTechUITextures; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class GodforgeExoticFrontend extends RecipeMapFrontend { + + public GodforgeExoticFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super(uiPropertiesBuilder, neiPropertiesBuilder); + } + + @Override + public void addGregTechLogo(ModularWindow.Builder builder, Pos2d windowOffset) { + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_LOGO) + .setSize(18, 18) + .setPos(new Pos2d(151, 63).add(windowOffset))); + } + + @Override + public void drawNEIOverlays(GTNEIDefaultHandler.CachedDefaultRecipe neiCachedRecipe) { + if (neiCachedRecipe.mRecipe.mFluidOutputs[0].equals(MaterialsUEVplus.QuarkGluonPlasma.getFluid(1000))) { + neiCachedRecipe.mInputs.set(0, new PositionedStack(quarkGluonItemsForNEI, 48, 23, true)); + neiCachedRecipe.mInputs.set(1, new PositionedStack(quarkGluonFluidItemsForNEI, 48, 52, true)); + } else { + neiCachedRecipe.mInputs.set(0, new PositionedStack(magmatterItemsForNEI, 48, 23, true)); + neiCachedRecipe.mInputs.set(1, new PositionedStack(magmatterSpaceFluidItemsForNEI, 30, 52, true)); + neiCachedRecipe.mInputs.set(2, new PositionedStack(magmatterTimeFluidItemsForNEI, 48, 52, true)); + } + } + + @Override + public List<Pos2d> getItemInputPositions(int itemInputCount) { + return Collections.singletonList(new Pos2d(52, 33)); + } + + @Override + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return Collections.singletonList(new Pos2d(106, 33)); + } + + @Override + protected void drawEnergyInfo(RecipeDisplayInfo recipeInfo) { + long eut = recipeInfo.recipe.mEUt; + long duration = recipeInfo.recipe.mDuration; + recipeInfo.drawText(trans("152", "Total: ") + GTUtility.formatNumbers(eut * duration) + " EU"); + recipeInfo.drawText(trans("153", "Usage: ") + GTUtility.formatNumbers(eut) + " EU/t"); + recipeInfo.drawText(trans("158", "Time: ") + GTUtility.formatNumbers(duration / 20) + " secs"); + + } + + @Override + protected void drawDurationInfo(RecipeDisplayInfo recipeInfo) {} + +} diff --git a/src/main/java/tectech/recipe/GodforgePlasmaFrontend.java b/src/main/java/tectech/recipe/GodforgePlasmaFrontend.java new file mode 100644 index 0000000000..5dfc46b1cf --- /dev/null +++ b/src/main/java/tectech/recipe/GodforgePlasmaFrontend.java @@ -0,0 +1,79 @@ +package tectech.recipe; + +import static gregtech.api.util.GTUtility.trans; +import static net.minecraft.util.StatCollector.translateToLocal; + +import java.util.Collections; +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; + +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MethodsReturnNonnullByDefault; +import gregtech.nei.RecipeDisplayInfo; +import tectech.thing.gui.TecTechUITextures; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class GodforgePlasmaFrontend extends RecipeMapFrontend { + + public GodforgePlasmaFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super(uiPropertiesBuilder, neiPropertiesBuilder); + } + + @Override + public void addGregTechLogo(ModularWindow.Builder builder, Pos2d windowOffset) { + builder.widget( + new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_LOGO) + .setSize(18, 18) + .setPos(new Pos2d(151, 63).add(windowOffset))); + } + + @Override + public List<Pos2d> getItemInputPositions(int itemInputCount) { + return Collections.singletonList(new Pos2d(52, 33)); + } + + @Override + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return Collections.singletonList(new Pos2d(106, 33)); + } + + @Override + protected void drawEnergyInfo(RecipeDisplayInfo recipeInfo) { + long eut = recipeInfo.recipe.mEUt; + long duration = recipeInfo.recipe.mDuration; + String multistep = "No"; + if (recipeInfo.recipe.mSpecialItems.toString() + .equals("true")) { + multistep = "Yes"; + } + String requiredUpgrade = switch (recipeInfo.recipe.mSpecialValue) { + case 1 -> "T4-T5"; + case 2 -> "Exotic"; + default -> "T1-T3"; + }; + + recipeInfo.drawText(trans("152", "Total: ") + GTUtility.formatNumbers(eut * duration) + " EU"); + recipeInfo.drawText(trans("153", "Usage: ") + GTUtility.formatNumbers(eut) + " EU/t"); + recipeInfo.drawText( + trans("158", "Time: ") + GTUtility.formatNumbers(duration / 20d) + + " secs" + + (duration < 20 ? " (" + duration + " ticks)" : "")); + recipeInfo.drawText(translateToLocal("gt.blockmachines.multimachine.FOG.plasmamultistep") + ": " + multistep); + recipeInfo + .drawText(translateToLocal("gt.blockmachines.multimachine.FOG.plasmarecipetier") + ": " + requiredUpgrade); + } + + @Override + protected void drawDurationInfo(RecipeDisplayInfo recipeInfo) {} + +} diff --git a/src/main/java/tectech/recipe/ResearchStationFrontend.java b/src/main/java/tectech/recipe/ResearchStationFrontend.java new file mode 100644 index 0000000000..ce26215fbb --- /dev/null +++ b/src/main/java/tectech/recipe/ResearchStationFrontend.java @@ -0,0 +1,101 @@ +package tectech.recipe; + +import static gregtech.api.util.GTUtility.trans; +import static net.minecraft.util.StatCollector.translateToLocalFormatted; + +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.common.widget.ProgressBar; + +import gregtech.api.recipe.BasicUIPropertiesBuilder; +import gregtech.api.recipe.NEIRecipePropertiesBuilder; +import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MethodsReturnNonnullByDefault; +import gregtech.nei.RecipeDisplayInfo; +import tectech.thing.gui.TecTechUITextures; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class ResearchStationFrontend extends RecipeMapFrontend { + + public ResearchStationFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, + NEIRecipePropertiesBuilder neiPropertiesBuilder) { + super(uiPropertiesBuilder, neiPropertiesBuilder); + } + + @Override + public List<Pos2d> getItemInputPositions(int itemInputCount) { + return Collections.singletonList(new Pos2d(52, 33)); + } + + @Override + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return Collections.singletonList(new Pos2d(106, 33)); + } + + @Override + public Pos2d getSpecialItemPosition() { + return new Pos2d(124, 62); + } + + @Override + protected void drawEnergyInfo(RecipeDisplayInfo recipeInfo) { + long eut = recipeInfo.recipe.mEUt; + int computation = recipeInfo.recipe.mDuration; + short ampere = (short) (recipeInfo.recipe.mSpecialValue & 0xFFFF); + short minComputationPerSec = (short) (recipeInfo.recipe.mSpecialValue >>> 16); + recipeInfo.drawText( + translateToLocalFormatted( + "tt.nei.research.max_eu", + GTUtility.formatNumbers( + (1 + (computation - minComputationPerSec) / minComputationPerSec) * eut * ampere * 20))); + recipeInfo.drawText(trans("153", "Usage: ") + GTUtility.formatNumbers(eut * ampere) + " EU/t"); + recipeInfo.drawText(trans("154", "Voltage: ") + GTUtility.formatNumbers(eut) + " EU/t"); + recipeInfo.drawText(trans("155", "Amperage: ") + GTUtility.formatNumbers(ampere)); + recipeInfo + .drawText(translateToLocalFormatted("tt.nei.research.computation", GTUtility.formatNumbers(computation))); + recipeInfo.drawText( + translateToLocalFormatted( + "tt.nei.research.min_computation", + GTUtility.formatNumbers(minComputationPerSec))); + } + + @Override + protected void drawDurationInfo(RecipeDisplayInfo recipeInfo) {} + + @Override + public void addProgressBar(ModularWindow.Builder builder, Supplier<Float> progressSupplier, Pos2d windowOffset) { + int bar1Width = 25; + int bar2Width = 11; + int bar3Height = 18; + List<Supplier<Float>> splitProgress = splitProgress(progressSupplier, bar1Width, bar2Width, bar3Height); + builder.widget( + new ProgressBar().setTexture(TecTechUITextures.PROGRESSBAR_RESEARCH_STATION_1, bar1Width) + .setDirection(ProgressBar.Direction.RIGHT) + .setProgress(splitProgress.get(0)) + .setSynced(false, false) + .setPos(new Pos2d(81, 40).add(windowOffset)) + .setSize(bar1Width, 5)); + builder.widget( + new ProgressBar().setTexture(TecTechUITextures.PROGRESSBAR_RESEARCH_STATION_2, bar2Width) + .setDirection(ProgressBar.Direction.RIGHT) + .setProgress(splitProgress.get(1)) + .setSynced(false, false) + .setPos(new Pos2d(124, 40).add(windowOffset)) + .setSize(bar2Width, 5)); + builder.widget( + new ProgressBar().setTexture(TecTechUITextures.PROGRESSBAR_RESEARCH_STATION_3, bar3Height) + .setDirection(ProgressBar.Direction.DOWN) + .setProgress(splitProgress.get(2)) + .setSynced(false, false) + .setPos(new Pos2d(128, 44).add(windowOffset)) + .setSize(10, bar3Height)); + } +} diff --git a/src/main/java/tectech/recipe/TTRecipeAdder.java b/src/main/java/tectech/recipe/TTRecipeAdder.java new file mode 100644 index 0000000000..69068afce0 --- /dev/null +++ b/src/main/java/tectech/recipe/TTRecipeAdder.java @@ -0,0 +1,251 @@ +package tectech.recipe; + +import static gregtech.api.recipe.RecipeMaps.assemblylineVisualRecipes; +import static gregtech.api.util.GTRecipeConstants.RESEARCH_STATION_DATA; +import static tectech.recipe.TecTechRecipeMaps.researchStationFakeRecipes; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import cpw.mods.fml.common.registry.GameRegistry; +import gregtech.api.enums.GTValues; +import gregtech.api.enums.ItemList; +import gregtech.api.util.AssemblyLineUtils; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTRecipe.RecipeAssemblyLine; +import gregtech.api.util.GTUtility; +import gregtech.common.RecipeAdder; +import tectech.TecTech; +import tectech.thing.CustomItemList; + +public class TTRecipeAdder extends RecipeAdder { + + public static final ItemStack[] nullItem = new ItemStack[0]; + public static final FluidStack[] nullFluid = new FluidStack[0]; + + @Deprecated + public static boolean addResearchableAssemblylineRecipe(ItemStack aResearchItem, int totalComputationRequired, + int computationRequiredPerSec, int researchEUt, int researchAmperage, ItemStack[] aInputs, + FluidStack[] aFluidInputs, ItemStack aOutput, int assDuration, int assEUt) { + if (aInputs == null) { + aInputs = nullItem; + } + if (aFluidInputs == null) { + aFluidInputs = nullFluid; + } + if (aResearchItem == null || totalComputationRequired <= 0 || aOutput == null || aInputs.length > 16) { + return false; + } + for (ItemStack tItem : aInputs) { + if (tItem == null) { + TecTech.LOGGER.error( + "addResearchableAssemblingLineRecipe " + aResearchItem.getDisplayName() + + " --> " + + aOutput.getUnlocalizedName() + + " there is some null item in that recipe"); + } + } + researchAmperage = GTUtility.clamp(researchAmperage, 1, Short.MAX_VALUE); + computationRequiredPerSec = GTUtility.clamp(computationRequiredPerSec, 1, Short.MAX_VALUE); + + GTRecipe.RecipeAssemblyLine recipeGT = new GTRecipe.RecipeAssemblyLine( + CustomItemList.UnusedStuff.get(1), + totalComputationRequired / computationRequiredPerSec, + aInputs, + aFluidInputs, + aOutput, + assDuration, + assEUt); + RecipeAssemblyLine recipeTT = new GTRecipe.RecipeAssemblyLine( + aResearchItem, + totalComputationRequired / computationRequiredPerSec, + aInputs, + aFluidInputs, + aOutput, + assDuration, + assEUt); + GTRecipe.RecipeAssemblyLine.sAssemblylineRecipes.add(recipeGT); + TecTechRecipeMaps.researchableALRecipeList.add(recipeTT); + + ItemStack writesDataStick = ItemList.Tool_DataStick.getWithName(1L, "Writes Research result"); + AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(writesDataStick, recipeTT, false); + GTValues.RA.stdBuilder() + .itemInputs(aResearchItem) + .itemOutputs(aOutput) + .special(writesDataStick) + .duration(totalComputationRequired) + .eut(researchEUt) + .metadata(RESEARCH_STATION_DATA, researchAmperage | computationRequiredPerSec << 16) + .noOptimize() + .ignoreCollision() + .fake() + .addTo(researchStationFakeRecipes); + + ItemStack readsDataStick = ItemList.Tool_DataStick.getWithName(1L, "Reads Research result"); + AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(readsDataStick, recipeTT, false); + GTValues.RA.stdBuilder() + .itemInputs(aInputs) + .itemOutputs(aOutput) + .fluidInputs(aFluidInputs) + .special(readsDataStick) + .duration(assDuration) + .eut(assEUt) + .ignoreCollision() + .fake() + .addTo(assemblylineVisualRecipes); + return true; + } + + @Deprecated + public static boolean addResearchableAssemblylineRecipe(ItemStack aResearchItem, int totalComputationRequired, + int computationRequiredPerSec, int researchEUt, int researchAmperage, Object[] aInputs, + FluidStack[] aFluidInputs, ItemStack aOutput, int assDuration, int assEUt) { + if (aInputs == null) { + aInputs = nullItem; + } + if (aFluidInputs == null) { + aFluidInputs = nullFluid; + } + if (aResearchItem == null || totalComputationRequired <= 0 + || aOutput == null + || aInputs.length > 16 + || aFluidInputs.length > 4 + || assDuration <= 0 + || assEUt <= 0) { + return false; + } + + ItemStack[] tInputs = new ItemStack[aInputs.length]; + ItemStack[][] tAlts = new ItemStack[aInputs.length][]; + int tPersistentHash = 1; + for (int i = 0; i < aInputs.length; i++) { + Object obj = aInputs[i]; + if (obj instanceof ItemStack) { + tInputs[i] = (ItemStack) obj; + tAlts[i] = null; + tPersistentHash = tPersistentHash * 31 + GTUtility.persistentHash(tInputs[i], true, false); + continue; + } else if (obj instanceof ItemStack[]aStacks) { + if (aStacks.length > 0) { + tInputs[i] = aStacks[0]; + tAlts[i] = Arrays.copyOf(aStacks, aStacks.length); + for (ItemStack tAlt : tAlts[i]) { + tPersistentHash = tPersistentHash * 31 + GTUtility.persistentHash(tAlt, true, false); + } + tPersistentHash *= 31; + continue; + } + } else if (obj instanceof Object[]objs) { + List<ItemStack> tList; + if (objs.length >= 2 && !(tList = GTOreDictUnificator.getOres(objs[0])).isEmpty()) { + try { + // sort the output, so the hash code is stable across launches + tList.sort( + Comparator + .<ItemStack, String>comparing( + s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).modId) + .thenComparing(s -> GameRegistry.findUniqueIdentifierFor(s.getItem()).modId) + .thenComparingInt(Items.feather::getDamage) + .thenComparingInt(s -> s.stackSize)); + int tAmount = ((Number) objs[1]).intValue(); + List<ItemStack> uList = new ArrayList<>(); + for (ItemStack tStack : tList) { + ItemStack uStack = GTUtility.copyAmount(tAmount, tStack); + if (GTUtility.isStackValid(uStack)) { + uList.add(uStack); + if (tInputs[i] == null) tInputs[i] = uStack; + } + } + tAlts[i] = uList.toArray(new ItemStack[0]); + tPersistentHash = tPersistentHash * 31 + (objs[0] == null ? "" : objs[0].toString()).hashCode(); + tPersistentHash = tPersistentHash * 31 + tAmount; + continue; + } catch (Exception t) { + TecTech.LOGGER.error( + "addAssemblingLineRecipe " + aResearchItem.getDisplayName() + + " --> there is some ... in that recipe"); + } + } + } + TecTech.LOGGER.error( + "addAssemblingLineRecipe " + aResearchItem.getDisplayName() + + " --> " + + aOutput.getUnlocalizedName() + + " there is some null item in that recipe"); + } + tPersistentHash = tPersistentHash * 31 + GTUtility.persistentHash(aResearchItem, true, false); + tPersistentHash = tPersistentHash * 31 + GTUtility.persistentHash(aOutput, true, false); + for (FluidStack tFluidInput : aFluidInputs) { + if (tFluidInput == null) continue; + tPersistentHash = tPersistentHash * 31 + GTUtility.persistentHash(tFluidInput, true, false); + } + researchAmperage = GTUtility.clamp(researchAmperage, 1, Short.MAX_VALUE); + computationRequiredPerSec = GTUtility.clamp(computationRequiredPerSec, 1, Short.MAX_VALUE); + tPersistentHash = tPersistentHash * 31 + totalComputationRequired; + tPersistentHash = tPersistentHash * 31 + computationRequiredPerSec; + tPersistentHash = tPersistentHash * 31 + researchAmperage; + tPersistentHash = tPersistentHash * 31 + researchEUt; + tPersistentHash = tPersistentHash * 31 + assDuration; + tPersistentHash = tPersistentHash * 31 + assEUt; + + GTRecipe.RecipeAssemblyLine recipeGT = new GTRecipe.RecipeAssemblyLine( + CustomItemList.UnusedStuff.get(1), + totalComputationRequired / computationRequiredPerSec, + tInputs, + aFluidInputs, + aOutput, + assDuration, + assEUt, + tAlts); + recipeGT.setPersistentHash(tPersistentHash); + GTRecipe.RecipeAssemblyLine.sAssemblylineRecipes.add(recipeGT); + GTRecipe.RecipeAssemblyLine recipeTT = new GTRecipe.RecipeAssemblyLine( + aResearchItem, + totalComputationRequired / computationRequiredPerSec, + tInputs, + aFluidInputs, + aOutput, + assDuration, + assEUt, + tAlts); + recipeTT.setPersistentHash(tPersistentHash); + TecTechRecipeMaps.researchableALRecipeList.add(recipeTT); + + ItemStack writesDataStick = ItemList.Tool_DataStick.getWithName(1L, "Writes Research result"); + AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(writesDataStick, recipeTT, false); + GTValues.RA.stdBuilder() + .itemInputs(aResearchItem) + .itemOutputs(aOutput) + .special(writesDataStick) + .duration(totalComputationRequired) + .eut(researchEUt) + .metadata(RESEARCH_STATION_DATA, researchAmperage | computationRequiredPerSec << 16) + .noOptimize() + .ignoreCollision() + .fake() + .addTo(researchStationFakeRecipes); + + ItemStack readsDataStick = ItemList.Tool_DataStick.getWithName(1L, "Reads Research result"); + AssemblyLineUtils.setAssemblyLineRecipeOnDataStick(readsDataStick, recipeTT, false); + assemblylineVisualRecipes.addFakeRecipe( + false, + tInputs, + new ItemStack[] { aOutput }, + new ItemStack[] { readsDataStick }, + aFluidInputs, + null, + assDuration, + assEUt, + 0, + tAlts, + false); + return true; + } +} diff --git a/src/main/java/tectech/recipe/TecTechRecipeMaps.java b/src/main/java/tectech/recipe/TecTechRecipeMaps.java new file mode 100644 index 0000000000..b1c3608f45 --- /dev/null +++ b/src/main/java/tectech/recipe/TecTechRecipeMaps.java @@ -0,0 +1,78 @@ +package tectech.recipe; + +import java.util.ArrayList; +import java.util.List; + +import com.gtnewhorizons.modularui.common.widget.ProgressBar; + +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.recipe.RecipeMapBackend; +import gregtech.api.recipe.RecipeMapBuilder; +import gregtech.api.util.GTRecipe; +import tectech.thing.CustomItemList; +import tectech.thing.gui.TecTechUITextures; + +public class TecTechRecipeMaps { + + public static void init() {} + + public static final List<GTRecipe.RecipeAssemblyLine> researchableALRecipeList = new ArrayList<>(); + + public static final RecipeMap<RecipeMapBackend> eyeOfHarmonyRecipes = RecipeMapBuilder.of("gt.recipe.eyeofharmony") + .maxIO( + EyeOfHarmonyFrontend.maxItemInputs, + EyeOfHarmonyFrontend.maxItemOutputs, + EyeOfHarmonyFrontend.maxFluidInputs, + EyeOfHarmonyFrontend.maxFluidOutputs) + .minInputs(1, 0) + .progressBar(GTUITextures.PROGRESSBAR_HAMMER, ProgressBar.Direction.DOWN) + .progressBarPos(78, 24 + 2) + .logoPos(10, 10) + .neiHandlerInfo( + builder -> builder.setDisplayStack(CustomItemList.Machine_Multi_EyeOfHarmony.get(1)) + .setHeight(314) + .setMaxRecipesPerPage(1)) + .frontend(EyeOfHarmonyFrontend::new) + .build(); + public static final RecipeMap<RecipeMapBackend> researchStationFakeRecipes = RecipeMapBuilder + .of("gt.recipe.researchStation") + .maxIO(1, 1, 0, 0) + .useSpecialSlot() + .slotOverlays((index, isFluid, isOutput, isSpecial) -> { + if (isSpecial) { + return GTUITextures.OVERLAY_SLOT_DATA_ORB; + } + if (isOutput) { + return TecTechUITextures.OVERLAY_SLOT_MESH; + } + return GTUITextures.OVERLAY_SLOT_MICROSCOPE; + }) + .addSpecialTexture(19, 12, 84, 60, TecTechUITextures.PICTURE_HEAT_SINK) + .addSpecialTexture(41, 22, 40, 40, TecTechUITextures.PICTURE_RACK_LARGE) + .logo(TecTechUITextures.PICTURE_TECTECH_LOGO) + .logoSize(18, 18) + .logoPos(151, 63) + .neiTransferRect(81, 33, 25, 18) + .neiTransferRect(124, 33, 18, 29) + .frontend(ResearchStationFrontend::new) + .neiHandlerInfo(builder -> builder.setDisplayStack(CustomItemList.Machine_Multi_Research.get(1))) + .build(); + + public static final RecipeMap<RecipeMapBackend> godforgePlasmaRecipes = RecipeMapBuilder.of("gt.recipe.fog_plasma") + .maxIO(1, 1, 1, 1) + .progressBar(TecTechUITextures.PROGRESSBAR_GODFORGE_PLASMA, ProgressBar.Direction.RIGHT) + .progressBarPos(78, 33) + .neiTransferRect(78, 33, 20, 20) + .frontend(GodforgePlasmaFrontend::new) + .build(); + public static final RecipeMap<RecipeMapBackend> godforgeExoticMatterRecipes = RecipeMapBuilder + .of("gt.recipe.fog_exotic") + .maxIO(1, 1, 2, 1) + .progressBar(TecTechUITextures.PROGRESSBAR_GODFORGE_PLASMA, ProgressBar.Direction.RIGHT) + .progressBarPos(78, 33) + .neiTransferRect(78, 33, 20, 20) + .frontend(GodforgeExoticFrontend::new) + .build(); + +} |