diff options
| author | Abdiel Kavash <19243993+AbdielKavash@users.noreply.github.com> | 2024-02-28 05:45:44 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-28 12:45:44 +0100 |
| commit | 5497075f54732ccf3c7580fe311a2327ebb05cb2 (patch) | |
| tree | 8060f3d7bed0d8d62426541e83307f051a03da02 | |
| parent | ece12a200879adfb16fd9d8701f6e75a3d7c072e (diff) | |
| download | GT5-Unofficial-5497075f54732ccf3c7580fe311a2327ebb05cb2.tar.gz GT5-Unofficial-5497075f54732ccf3c7580fe311a2327ebb05cb2.tar.bz2 GT5-Unofficial-5497075f54732ccf3c7580fe311a2327ebb05cb2.zip | |
Tree Growth Simulator can now harvest leaves and fruits, using appropriate tools. (#839)
* TGS logic rework and new outputs
* TGS logic rework and new outputs
* NEI frontend.
* NEI frontend part 2
* Recover saws from controller slot to input bus.
* Added documentation and removed unused stuff.
* Recipes for non-Forestry trees.
* Updated tooltip.
* Better handling of saws in controller slot from previous versions + grafter support.
* Added Forestry and Extra Trees trees registration and processing.
* BS + deps.
* Disable ME stocking bus to fix an exploit.
* Fixes based on feedback.
---------
Co-authored-by: Martin Robertz <dream-master@gmx.net>
10 files changed, 1437 insertions, 522 deletions
diff --git a/src/main/java/gtPlusPlus/api/recipe/GTPPRecipeMaps.java b/src/main/java/gtPlusPlus/api/recipe/GTPPRecipeMaps.java index 3977d69fe7..f28216450d 100644 --- a/src/main/java/gtPlusPlus/api/recipe/GTPPRecipeMaps.java +++ b/src/main/java/gtPlusPlus/api/recipe/GTPPRecipeMaps.java @@ -21,6 +21,7 @@ import gregtech.nei.formatter.SimpleSpecialValueFormatter; import gtPlusPlus.core.util.math.MathUtils; import gtPlusPlus.core.util.minecraft.ItemUtils; import gtPlusPlus.xmod.gregtech.api.gui.GTPP_UITextures; +import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.GregtechMetaTileEntityTreeFarm; public class GTPPRecipeMaps { @@ -153,5 +154,11 @@ public class GTPPRecipeMaps { public static final RecipeMap<RecipeMapBackend> flotationCellRecipes = RecipeMapBuilder .of("gtpp.recipe.flotationcell").maxIO(6, 0, 1, 1).build(); public static final RecipeMap<RecipeMapBackend> treeGrowthSimulatorFakeRecipes = RecipeMapBuilder - .of("gtpp.recipe.treefarm").maxIO(1, 2, 1, 0).minInputs(1, 0).frontend(TGSFrontend::new).build(); + .of("gtpp.recipe.treefarm") + .maxIO( + GregtechMetaTileEntityTreeFarm.Mode.values().length, + GregtechMetaTileEntityTreeFarm.Mode.values().length, + 0, + 0) + .minInputs(1, 0).useSpecialSlot().frontend(TGSFrontend::new).build(); } diff --git a/src/main/java/gtPlusPlus/api/recipe/TGSFrontend.java b/src/main/java/gtPlusPlus/api/recipe/TGSFrontend.java index 10a9fe4da6..b36bf62b56 100644 --- a/src/main/java/gtPlusPlus/api/recipe/TGSFrontend.java +++ b/src/main/java/gtPlusPlus/api/recipe/TGSFrontend.java @@ -1,68 +1,146 @@ package gtPlusPlus.api.recipe; -import static net.minecraft.util.EnumChatFormatting.GRAY; - +import java.awt.Rectangle; import java.util.Arrays; -import java.util.Collections; import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.StatCollector; +import com.gtnewhorizons.modularui.api.math.Pos2d; + import gregtech.api.recipe.BasicUIPropertiesBuilder; import gregtech.api.recipe.NEIRecipePropertiesBuilder; import gregtech.api.recipe.RecipeMapFrontend; +import gregtech.api.util.GT_Recipe; import gregtech.api.util.MethodsReturnNonnullByDefault; +import gregtech.common.gui.modularui.UIHelper; import gregtech.nei.GT_NEI_DefaultHandler; import gregtech.nei.RecipeDisplayInfo; import gregtech.nei.formatter.INEISpecialInfoFormatter; -import gtPlusPlus.core.item.ModItems; +import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.GregtechMetaTileEntityTreeFarm; +import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.GregtechMetaTileEntityTreeFarm.Mode; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class TGSFrontend extends RecipeMapFrontend { + private static final int SLOT_SIZE = 18; + private static final int CENTER_X = 90; + private static final int SPECIAL_X = CENTER_X - SLOT_SIZE / 2; + private static final int SPECIAL_Y = 9; + private static final int INPUTS_X = CENTER_X - SLOT_SIZE * 3; + private static final int INPUTS_Y = SPECIAL_Y + SLOT_SIZE + SLOT_SIZE / 2; + private static final int OUTPUTS_X = CENTER_X + SLOT_SIZE; + private static final int OUTPUTS_Y = INPUTS_Y; + public TGSFrontend(BasicUIPropertiesBuilder uiPropertiesBuilder, NEIRecipePropertiesBuilder neiPropertiesBuilder) { - super(uiPropertiesBuilder, neiPropertiesBuilder.neiSpecialInfoFormatter(new TGSSpecialValueFormatter())); + super( + uiPropertiesBuilder.addNEITransferRect( + new Rectangle(INPUTS_X + SLOT_SIZE * 2, INPUTS_Y + SLOT_SIZE / 2, SLOT_SIZE * 2, SLOT_SIZE)) + .progressBarPos(new Pos2d(CENTER_X - 10, INPUTS_Y + SLOT_SIZE / 2)), + neiPropertiesBuilder.neiSpecialInfoFormatter(new TGSSpecialValueFormatter())); } @Override - protected void drawEnergyInfo(RecipeDisplayInfo recipeInfo) {} + protected void drawEnergyInfo(RecipeDisplayInfo recipeInfo) { + // Do not. + } @Override - protected void drawDurationInfo(RecipeDisplayInfo recipeInfo) {} + public Pos2d getSpecialItemPosition() { + return new Pos2d(SPECIAL_X, SPECIAL_Y); + } @Override - protected List<String> handleNEIItemOutputTooltip(List<String> currentTip, - GT_NEI_DefaultHandler.FixedPositionedStack pStack) { - if (ModItems.fluidFertBasic != null && pStack.isChanceBased()) { - currentTip.add( - GRAY + StatCollector.translateToLocalFormatted( - "gtpp.nei.tgs.sapling", - StatCollector.translateToLocal(ModItems.fluidFertBasic.getUnlocalizedName()))); - } else { - super.handleNEIItemOutputTooltip(currentTip, pStack); - } - return currentTip; + public List<Pos2d> getItemInputPositions(int itemInputCount) { + return UIHelper.getGridPositions(Mode.values().length, INPUTS_X, INPUTS_Y, 2); } @Override - protected void drawNEIOverlayForOutput(GT_NEI_DefaultHandler.FixedPositionedStack stack) {} + public List<Pos2d> getItemOutputPositions(int itemOutputCount) { + return UIHelper.getGridPositions(Mode.values().length, OUTPUTS_X, OUTPUTS_Y, 2); + } + + private static final String[] tooltipInputs = { StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.saw"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.cutter"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.shears"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.knife") }; + + private static final String[] tooltipOutputs = { StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.needsSaw"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.needsCutter"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.needsShears"), + StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.needsKnife") }; + private static final String tooltipSapling = StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.sapling"); + private static final String tooltipMultiplier = StatCollector.translateToLocal("gtpp.nei.tgs.tooltip.multiplier"); + + @Override + public List<String> handleNEIItemTooltip(ItemStack stack, List<String> currentTip, + GT_NEI_DefaultHandler.CachedDefaultRecipe neiCachedRecipe) { + + /* + * This gets a little complicated, because we want to assign tooltips to inputs/outputs based on which mode + * (saw, shears, etc.) they correspond to. But CachedDefaultRecipe does not retain this information for us. This + * is because some recipes don't output any items for some modes. For example, if a recipe only yields logs and + * leaves, then the outputs of GT_Recipe will be {log, null, leaves}. However, in CachedDefaultRecipe this gets + * condensed to just {log, leaves}, with null values omitted. So to figure out which item came from which mode, + * we need to step through both of these arrays simultaneously and match non-null inputs/outputs in GT_Recipe to + * inputs/outputs in CachedDefaultRecipe. + */ + + // The last input in neiCachedRecipe is always the special slot, this is the input sapling. + if (stack == neiCachedRecipe.mInputs.get(neiCachedRecipe.mInputs.size() - 1).item) { + currentTip.add(EnumChatFormatting.YELLOW + tooltipSapling); + super.handleNEIItemTooltip(stack, currentTip, neiCachedRecipe); + return currentTip; + } + + GT_Recipe.GT_Recipe_WithAlt recipe = (GT_Recipe.GT_Recipe_WithAlt) neiCachedRecipe.mRecipe; + + // Inputs + int slot = 0; + for (int mode = 0; mode < Mode.values().length; ++mode) { + if (mode < recipe.mOreDictAlt.length && recipe.mOreDictAlt[mode] != null) { + // There is a valid input in this mode. + if (slot < neiCachedRecipe.mInputs.size() && stack == neiCachedRecipe.mInputs.get(slot).item) { + int toolMultiplier = GregtechMetaTileEntityTreeFarm.getToolMultiplier(stack, Mode.values()[mode]); + currentTip.add(EnumChatFormatting.YELLOW + tooltipInputs[mode]); + if (toolMultiplier > 0) { + currentTip.add(EnumChatFormatting.YELLOW + tooltipMultiplier + " " + toolMultiplier + "x"); + } + return currentTip; + } + ++slot; + } + } + + // Outputs + slot = 0; + for (int mode = 0; mode < Mode.values().length; ++mode) { + if (mode < recipe.mOutputs.length && recipe.mOutputs[mode] != null) { + // There is a valid output in this mode. + if (slot < neiCachedRecipe.mOutputs.size() && stack == neiCachedRecipe.mOutputs.get(slot).item) { + currentTip.add(EnumChatFormatting.YELLOW + tooltipOutputs[mode]); + return currentTip; + } + ++slot; + } + } + + return currentTip; + } private static class TGSSpecialValueFormatter implements INEISpecialInfoFormatter { @Override public List<String> format(RecipeDisplayInfo recipeInfo) { - if (ModItems.fluidFertBasic == null) { - return Collections.emptyList(); - } return Arrays.asList( - StatCollector.translateToLocal("gtpp.nei.tgs.1"), - StatCollector.translateToLocalFormatted( - "gtpp.nei.tgs.2", - StatCollector.translateToLocal(ModItems.fluidFertBasic.getUnlocalizedName())), - StatCollector.translateToLocal("gtpp.nei.tgs.3")); + StatCollector.translateToLocal("gtpp.nei.tgs.info-1"), + StatCollector.translateToLocal("gtpp.nei.tgs.info-2"), + StatCollector.translateToLocal("gtpp.nei.tgs.info-3")); } } } diff --git a/src/main/java/gtPlusPlus/xmod/forestry/HANDLER_FR.java b/src/main/java/gtPlusPlus/xmod/forestry/HANDLER_FR.java index 80d1620f02..a1b96d0f2f 100644 --- a/src/main/java/gtPlusPlus/xmod/forestry/HANDLER_FR.java +++ b/src/main/java/gtPlusPlus/xmod/forestry/HANDLER_FR.java @@ -1,22 +1,10 @@ package gtPlusPlus.xmod.forestry; -import static gregtech.api.enums.Mods.ExtraTrees; import static gregtech.api.enums.Mods.Forestry; -import net.minecraft.item.ItemStack; - -import binnie.extratrees.genetics.ExtraTreeSpecies; -import cpw.mods.fml.common.Optional; -import forestry.api.arboriculture.EnumGermlingType; -import forestry.api.arboriculture.EnumWoodType; -import forestry.api.arboriculture.TreeManager; -import forestry.arboriculture.genetics.TreeDefinition; -import gregtech.api.enums.Mods; -import gtPlusPlus.core.util.reflect.ReflectionUtils; import gtPlusPlus.xmod.forestry.bees.items.FR_ItemRegistry; import gtPlusPlus.xmod.forestry.bees.recipe.FR_Gregtech_Recipes; import gtPlusPlus.xmod.forestry.bees.registry.GTPP_Bees; -import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.GregtechMetaTileEntityTreeFarm; public class HANDLER_FR { @@ -30,51 +18,6 @@ public class HANDLER_FR { if (Forestry.isModLoaded()) { FR_Gregtech_Recipes.registerItems(); new GTPP_Bees(); - mapForestrySaplingToLog(); - } - - if (ExtraTrees.isModLoaded()) { - mapExtraTreesSaplingToLog(); - } - } - - @Optional.Method(modid = Mods.Names.FORESTRY) - private static void mapForestrySaplingToLog() { - for (TreeDefinition value : TreeDefinition.values()) { - ItemStack aSaplingStack = value.getMemberStack(EnumGermlingType.SAPLING); - EnumWoodType woodType = ReflectionUtils.getField(value, "woodType"); - ItemStack aLog; - if (woodType != null) { - aLog = TreeManager.woodItemAccess.getLog(woodType, false); - - GregtechMetaTileEntityTreeFarm.sLogCache.put(value.getUID(), aLog); - GregtechMetaTileEntityTreeFarm.sLogCache - .put(value.getUID() + "fireproof", TreeManager.woodItemAccess.getLog(woodType, true)); - } else { - aLog = ReflectionUtils.getField(value, "vanillaWood"); - - GregtechMetaTileEntityTreeFarm.sLogCache - .put(value.getUID(), ReflectionUtils.getField(value, "vanillaWood")); - } - - GregtechMetaTileEntityTreeFarm.addFakeRecipeToNEI(aSaplingStack, aLog); - } - } - - @Optional.Method(modid = Mods.Names.EXTRA_TREES) - private static void mapExtraTreesSaplingToLog() { - for (ExtraTreeSpecies value : ExtraTreeSpecies.values()) { - ItemStack aSaplingStack = TreeManager.treeRoot - .getMemberStack(TreeManager.treeRoot.templateAsIndividual(value.getTemplate()), 0); - ItemStack aLog = null; - if (value.getLog() != null) { - aLog = value.getLog().getItemStack(); - - GregtechMetaTileEntityTreeFarm.sLogCache.put(value.getUID(), aLog); - GregtechMetaTileEntityTreeFarm.sLogCache.put(value.getUID() + "fireproof", aLog); - } - - GregtechMetaTileEntityTreeFarm.addFakeRecipeToNEI(aSaplingStack, aLog); } } } diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/HANDLER_GT.java b/src/main/java/gtPlusPlus/xmod/gregtech/HANDLER_GT.java index 91dd851f84..e95baf43df 100644 --- a/src/main/java/gtPlusPlus/xmod/gregtech/HANDLER_GT.java +++ b/src/main/java/gtPlusPlus/xmod/gregtech/HANDLER_GT.java @@ -25,6 +25,7 @@ import gtPlusPlus.xmod.gregtech.loaders.ProcessingElectricSnips; import gtPlusPlus.xmod.gregtech.loaders.misc.AddCustomMachineToPA; import gtPlusPlus.xmod.gregtech.loaders.recipe.RecipeLoader_AlgaeFarm; import gtPlusPlus.xmod.gregtech.loaders.recipe.RecipeLoader_MolecularTransformer; +import gtPlusPlus.xmod.gregtech.loaders.recipe.RecipeLoader_TreeFarm; import gtPlusPlus.xmod.gregtech.registration.gregtech.GregtechConduits; public class HANDLER_GT { @@ -89,6 +90,7 @@ public class HANDLER_GT { CokeAndPyrolyseOven.onLoadComplete(); Meta_GT_Proxy.fixIC2FluidNames(); RecipeLoader_AlgaeFarm.generateRecipes(); + RecipeLoader_TreeFarm.generateRecipes(); if (AdvancedSolarPanel.isModLoaded()) { RecipeLoader_MolecularTransformer.run(); } diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java b/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java deleted file mode 100644 index 7774a34dc1..0000000000 --- a/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java +++ /dev/null @@ -1,37 +0,0 @@ -package gtPlusPlus.xmod.gregtech.common.helpers; - -import net.minecraft.item.ItemStack; - -import gregtech.common.items.GT_MetaGenerated_Tool_01; - -public class TreeFarmHelper { - - public static boolean isValidForGUI(final ItemStack aStack) { - return isCorrectMachinePart(aStack) != SAWTOOL.NONE; - } - - public static SAWTOOL isCorrectMachinePart(final ItemStack aStack) { - if (aStack != null && aStack.getItem() instanceof GT_MetaGenerated_Tool_01) { - switch (aStack.getItemDamage()) { - case GT_MetaGenerated_Tool_01.SAW -> { - return SAWTOOL.SAW; - } - case GT_MetaGenerated_Tool_01.BUZZSAW_LV, GT_MetaGenerated_Tool_01.BUZZSAW_MV, GT_MetaGenerated_Tool_01.BUZZSAW_HV -> { - return SAWTOOL.BUZZSAW; - } - case GT_MetaGenerated_Tool_01.CHAINSAW_LV, GT_MetaGenerated_Tool_01.CHAINSAW_MV, GT_MetaGenerated_Tool_01.CHAINSAW_HV -> { - return SAWTOOL.CHAINSAW; - } - } - } - return SAWTOOL.NONE; - } - - public enum SAWTOOL { - NONE, - SAW, - BUZZSAW, - CHAINSAW - } - -} diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntityTreeFarm.java b/src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntityTreeFarm.java index 832c84833c..5ce6c2db45 100644 --- a/src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntityTreeFarm.java +++ b/src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntityTreeFarm.java @@ -10,89 +10,72 @@ import static gregtech.api.enums.GT_HatchElement.Maintenance; import static gregtech.api.enums.GT_HatchElement.Muffler; import static gregtech.api.enums.GT_HatchElement.OutputBus; import static gregtech.api.enums.GT_HatchElement.OutputHatch; -import static gregtech.api.enums.Mods.BiomesOPlenty; -import static gregtech.api.enums.Mods.ForbiddenMagic; -import static gregtech.api.enums.Mods.GTPlusPlus; -import static gregtech.api.enums.Mods.GalaxySpace; -import static gregtech.api.enums.Mods.IndustrialCraft2; -import static gregtech.api.enums.Mods.Natura; -import static gregtech.api.enums.Mods.PamsHarvestCraft; -import static gregtech.api.enums.Mods.PamsHarvestTheNether; -import static gregtech.api.enums.Mods.TaintedMagic; -import static gregtech.api.enums.Mods.Thaumcraft; -import static gregtech.api.enums.Mods.ThaumicBases; -import static gregtech.api.enums.Mods.TinkerConstruct; -import static gregtech.api.enums.Mods.TwilightForest; -import static gregtech.api.enums.Mods.Witchery; import static gregtech.api.util.GT_StructureUtility.buildHatchAdder; +import static gregtech.api.util.GT_Utility.filterValidMTEs; import static gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.GregtechMeta_MultiBlockBase.GTPPHatchElement.TTEnergy; import java.util.ArrayList; +import java.util.EnumMap; import java.util.HashMap; +import java.util.List; import javax.annotation.Nonnull; -import net.minecraft.init.Blocks; +import net.minecraft.init.Items; import net.minecraft.item.Item; +import net.minecraft.item.ItemShears; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; -import org.jetbrains.annotations.NotNull; - import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.structure.StructureDefinition; -import forestry.api.arboriculture.EnumTreeChromosome; +import forestry.api.arboriculture.IToolGrafter; import forestry.api.arboriculture.ITree; import forestry.api.arboriculture.TreeManager; -import forestry.api.genetics.IAlleleBoolean; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.Mods; import gregtech.api.enums.TAE; import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.items.GT_MetaGenerated_Tool; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus; import gregtech.api.recipe.RecipeMap; import gregtech.api.recipe.check.CheckRecipeResult; import gregtech.api.recipe.check.CheckRecipeResultRegistry; import gregtech.api.recipe.check.SimpleCheckRecipeResult; import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; +import gregtech.api.util.GT_Recipe; import gregtech.api.util.GT_Utility; import gregtech.api.util.VoidProtectionHelper; +import gregtech.common.items.GT_MetaGenerated_Tool_01; +import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_InputBus_ME; import gtPlusPlus.api.objects.Logger; import gtPlusPlus.api.recipe.GTPPRecipeMaps; import gtPlusPlus.core.block.ModBlocks; -import gtPlusPlus.core.item.ModItems; import gtPlusPlus.core.lib.CORE; -import gtPlusPlus.core.util.math.MathUtils; -import gtPlusPlus.core.util.minecraft.FluidUtils; import gtPlusPlus.core.util.minecraft.ItemUtils; -import gtPlusPlus.core.util.minecraft.MaterialUtils; import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.GregtechMeta_MultiBlockBase; import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock; -import gtPlusPlus.xmod.gregtech.common.helpers.TreeFarmHelper; -import gtPlusPlus.xmod.gregtech.common.helpers.TreeFarmHelper.SAWTOOL; +import gtPlusPlus.xmod.gregtech.common.items.MetaGeneratedGregtechTools; public class GregtechMetaTileEntityTreeFarm extends GregtechMeta_MultiBlockBase<GregtechMetaTileEntityTreeFarm> implements ISurvivalConstructable { public static int CASING_TEXTURE_ID; - public static String mCasingName = "Sterile Farm Casing"; - public static HashMap<String, ItemStack> sLogCache = new HashMap<>(); private static final int TICKS_PER_OPERATION = 100; + private static final int TOOL_DAMAGE_PER_OPERATION = 1; + private static final int TOOL_CHARGE_PER_OPERATION = 32; private int mCasing; + public static String mCasingName = "Sterile Farm Casing"; private static IStructureDefinition<GregtechMetaTileEntityTreeFarm> STRUCTURE_DEFINITION = null; - private SAWTOOL mToolType; - private ItemStack mSapling; - private ItemStack mWood; - private float heightModifier = 1.0f; - private float saplingsModifier = 1.0f; - private int girthModifier = 1; - public GregtechMetaTileEntityTreeFarm(final int aID, final String aName, final String aNameRegional) { super(aID, aName, aNameRegional); CASING_TEXTURE_ID = TAE.getIndexFromPage(1, 15); @@ -116,20 +99,20 @@ public class GregtechMetaTileEntityTreeFarm extends GregtechMeta_MultiBlockBase< @Override protected GT_Multiblock_Tooltip_Builder createTooltip() { GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder(); - tt.addMachineType(getMachineType()).addInfo("Converts EU to Logs").addInfo("Eu Usage: 100% | Parallel: 1") - .addInfo("Requires a Saw or Chainsaw in GUI slot").addInfo("Output multiplier:").addInfo("Saw = 1x") - .addInfo("Buzzsaw = 2x").addInfo("Chainsaw = 4x") - .addInfo("Add a sapling in the input bus to select wood type output") - .addInfo("The sapling is not consumed").addInfo("Tools can also be fed to the controller via input bus") - .addInfo("The working speed is fixed for 5s") - .addInfo("Production Formula: (2 * tier^2 - 2 * tier + 5) * 5 * saw boost") - .addInfo("When fertilizer is supplied, produces saplings instead of logs") - .addInfo("Forestry saplings can get increased production") + tt.addMachineType(getMachineType()).addInfo("Controller block for the Tree Growth Simulator") + .addInfo("Farms and harvests trees using EU").addInfo("Place a sapling in the controller slot") + .addInfo("Place a tool in an input bus").addInfo("Different tools are required for different outputs") + .addInfo("Advanced tools multiply output amount") + .addInfo(" Logs: Saw (1x), Buzzsaw (2x), Chainsaw (4x)") + .addInfo(" Saplings: Branch Cutter (1x), Grafter (3x)") + .addInfo(" Leaves: Shears (1x), Wire Cutter (2x), Automatic Snips (4x)").addInfo(" Fruit: Knife (1x)") + .addInfo("Multiple tools can be used at the same time").addSeparator() + .addInfo("Work time is fixed at 5 seconds").addInfo("Energy input tier multiplies output further") + .addInfo("Output multiplier is equal to: 2*tier^2 - 2*tier + 5") .addPollutionAmount(getPollutionPerSecond(null)).addSeparator().beginStructureBlock(3, 3, 3, true) - .addController("Front center").addCasingInfoMin("Sterile Farm Casing", 8, false) - .addInputBus("Any casing", 1).addOutputBus("Any casing", 1).addEnergyHatch("Any casing", 1) - .addMaintenanceHatch("Any casing", 1).addMufflerHatch("Any casing", 1) - .toolTipFinisher(CORE.GT_Tooltip_Builder.get()); + .addController("Front center").addCasingInfoMin(mCasingName, 8, false).addInputBus("Any casing", 1) + .addOutputBus("Any casing", 1).addEnergyHatch("Any casing", 1).addMaintenanceHatch("Any casing", 1) + .addMufflerHatch("Any casing", 1).toolTipFinisher(CORE.GT_Tooltip_Builder.get()); return tt; } @@ -149,101 +132,58 @@ public class GregtechMetaTileEntityTreeFarm extends GregtechMeta_MultiBlockBase< } @Override - public boolean isCorrectMachinePart(final ItemStack aStack) { - // is correct part && either not powered tool or have enough power - if (TreeFarmHelper.isValidForGUI(aStack) - && GT_MetaGenerated_Tool.getToolDamage(aStack) < GT_MetaGenerated_Tool.getToolMaxDamage(aStack)) { - return GT_ModHandler.isElectricItem(aStack) ? GT_ModHandler.canUseElectricItem(aStack, 32) : true; - } - return false; + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + mCasing = 0; + return checkPiece(mName, 1, 1, 0) && mCasing >= 8 && checkHatch(); } - /** - * Method used to get the boost based on the ordinal of the saw - * - * @param sawType type of the saw - * @return an int corresponding to the boost - */ - public int getSawBoost(SAWTOOL sawType) { - return switch (sawType) { - case SAW -> 1; - case BUZZSAW -> 2; - case CHAINSAW -> 4; - default -> 1; - }; + @Override + public boolean checkHatch() { + // Tools from a stocking inout bus can not be damaged, this would cause an infinite durability exploit. + // Therefore disallow ME input bus. + if (!super.checkHatch()) return false; + for (GT_MetaTileEntity_Hatch_InputBus inputBus : mInputBusses) { + if (inputBus instanceof GT_MetaTileEntity_Hatch_InputBus_ME) { + return false; + } + } + return true; } @Override - public RecipeMap<?> getRecipeMap() { - // Only for visual - return GTPPRecipeMaps.treeGrowthSimulatorFakeRecipes; + public boolean supportsCraftingMEBuffer() { + return false; } @Override - public @NotNull CheckRecipeResult checkProcessing() { - final ItemStack controllerStack = getControllerSlot(); - if (!isCorrectMachinePart(controllerStack) && !replaceTool()) - return SimpleCheckRecipeResult.ofFailure("no_saw"); - if (!checkSapling()) return SimpleCheckRecipeResult.ofFailure("no_sapling"); - - this.mToolType = TreeFarmHelper.isCorrectMachinePart(controllerStack); - - long tVoltage = getMaxInputVoltage(); - byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage)); - - int aOutputAmount = ((2 * (tTier * tTier)) - (2 * tTier) + 5) * (TICKS_PER_OPERATION / 20) - * getSawBoost(mToolType); - int aFert = hasLiquidFert(); - ItemStack[] toOutput; - - if (aFert > 0) { // Sapling - if (aFert < aOutputAmount) { - aOutputAmount /= 10; - } - int amplifiedOutputAmount = (int) (aOutputAmount * saplingsModifier); - toOutput = new ItemStack[] { ItemUtils.getSimpleStack(mSapling, amplifiedOutputAmount) }; - } else { // Log - int amplifiedOutputAmount = (int) (aOutputAmount * heightModifier * girthModifier); - toOutput = new ItemStack[] { ItemUtils.getSimpleStack(mWood, amplifiedOutputAmount) }; - } - - VoidProtectionHelper voidProtection = new VoidProtectionHelper().setMachine(this).setItemOutputs(toOutput) - .build(); - - if (voidProtection.isItemFull()) { - return CheckRecipeResultRegistry.ITEM_OUTPUT_FULL; - } - - if (aFert > 0 && aFert >= aOutputAmount) { - tryConsumeLiquidFert(aOutputAmount); - } - - this.mOutputItems = toOutput; - - this.mMaxProgresstime = TICKS_PER_OPERATION; - this.lEUt = MaterialUtils.getVoltageForTier(tTier); + public int getMaxParallelRecipes() { + return 1; + } - this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000); - this.mEfficiencyIncrease = 10000; + @Override + public boolean supportsBatchMode() { + // Batch mode would not do anything, processing time is fixed at 100 ticks. + return false; + } - if (this.lEUt > 0) { - this.lEUt = (-this.lEUt); - } + @Override + public boolean isBatchModeEnabled() { + return false; + } - this.tryDamageTool(); - this.updateSlots(); - return SimpleCheckRecipeResult.ofSuccess("growing_trees"); + @Override + public int getMaxEfficiency(final ItemStack aStack) { + return 10000; } @Override - public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { - mCasing = 0; - return checkPiece(mName, 1, 1, 0) && mCasing >= 8 && checkHatch(); + public int getPollutionPerSecond(final ItemStack aStack) { + return CORE.ConfigSwitches.pollutionPerSecondMultiTreeFarm; } @Override - public int getMaxParallelRecipes() { - return 1; + public boolean explodesOnComponentBreak(final ItemStack aStack) { + return false; } @Override @@ -272,326 +212,574 @@ public class GregtechMetaTileEntityTreeFarm extends GregtechMeta_MultiBlockBase< } @Override - public int getMaxEfficiency(final ItemStack aStack) { - return 10000; + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece(mName, stackSize, hintsOnly, 1, 1, 0); } @Override - public int getPollutionPerSecond(final ItemStack aStack) { - return CORE.ConfigSwitches.pollutionPerSecondMultiTreeFarm; + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return survivialBuildPiece(mName, stackSize, 1, 1, 0, elementBudget, env, false, true); } + /* Processing logic. */ + @Override - public int getDamageToComponent(final ItemStack aStack) { - return MathUtils.balance((int) (75 - ((GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).getMass()))), 5, 120); + public boolean isCorrectMachinePart(final ItemStack aStack) { + if (aStack == null) return false; + if (isValidSapling(aStack)) return true; + /* + * In previous versions, a saw used to go in the controller slot. We do not want an update to stop processing of + * a machine set up like this. Instead, a sapling is placed in this slot at the start of the next operation. + */ + if (aStack.getItem() instanceof GT_MetaGenerated_Tool_01) return true; + return false; } @Override - public boolean explodesOnComponentBreak(final ItemStack aStack) { - return false; + public RecipeMap<?> getRecipeMap() { + // Only for NEI, not used in processing logic. + return GTPPRecipeMaps.treeGrowthSimulatorFakeRecipes; } - private boolean tryDamageTool() { - GT_ModHandler.damageOrDechargeItem(this.mInventory[1], 1, 32, null); - return replaceTool(); + /** + * Valid processing modes (types of output) for the Tree Growth Simulator. + */ + public enum Mode { + LOG, + SAPLING, + LEAVES, + FRUIT + } + + /** + * Edit this to change relative yields for different modes. For example, logs are output at 5 times the rate of + * saplings. + */ + private static final EnumMap<Mode, Integer> modeMultiplier = new EnumMap<>(Mode.class); + static { + modeMultiplier.put(Mode.LOG, 5); + modeMultiplier.put(Mode.SAPLING, 1); + modeMultiplier.put(Mode.LEAVES, 2); + modeMultiplier.put(Mode.FRUIT, 1); } - public boolean replaceTool() { - ItemStack invItem = this.mInventory[1]; - if (isCorrectMachinePart(invItem)) return true; - else { - if (invItem != null) { - this.mInventory[1] = null; - this.addOutput(invItem); + /** + * Return the output multiplier for a given power tier. + * + * @param tier Power tier the machine runs on. + * @return Factor to multiply all outputs by. + */ + private static int getTierMultiplier(int tier) { + /* + * Where does this formula come from? [12:57 AM] boubou_19: i did. Basically Pandoro measured the output of a + * WA-ed farming station for each tier of WA, then i computed the Lagrange interpolating polynomial of his + * dataset, which gave this + */ + return (2 * (tier * tier)) - (2 * tier) + 5; + } + + /** + * Key of this map is the registry name of the sapling, followed by ":", and the sapling's metadata value. + * <p> + * The value of the map is a list of products by {@link Mode}. Products for some modes can be null if the tree does + * not produce anything in that mode (for example, it has no fruit). + */ + public static final HashMap<String, EnumMap<Mode, ItemStack>> treeProductsMap = new HashMap<>(); + + @Override + public ProcessingLogic createProcessingLogic() { + return new ProcessingLogic() { + + @Override + @Nonnull + public CheckRecipeResult process() { + if (inputItems == null) { + inputItems = new ItemStack[0]; + } + if (inputFluids == null) { + inputFluids = new FluidStack[0]; + } + + ItemStack sapling = findSapling(); + if (sapling == null) return SimpleCheckRecipeResult.ofFailure("no_sapling"); + + EnumMap<Mode, ItemStack> outputPerMode = getOutputsForSapling(sapling); + if (outputPerMode == null) { + // This should usually not be possible, outputs for all valid saplings should be defined. + Logger.INFO("No output found for sapling: " + sapling.getDisplayName()); + return SimpleCheckRecipeResult.ofFailure("no_output_for_sapling"); + } + + int tier = Math.max(1, GT_Utility.getTier(availableVoltage * availableAmperage)); + int tierMultiplier = getTierMultiplier(tier); + + List<ItemStack> outputs = new ArrayList<>(); + for (Mode mode : Mode.values()) { |
