aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorAbdiel Kavash <19243993+AbdielKavash@users.noreply.github.com>2024-02-28 05:45:44 -0600
committerGitHub <noreply@github.com>2024-02-28 12:45:44 +0100
commit5497075f54732ccf3c7580fe311a2327ebb05cb2 (patch)
tree8060f3d7bed0d8d62426541e83307f051a03da02 /src/main
parentece12a200879adfb16fd9d8701f6e75a3d7c072e (diff)
downloadGT5-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>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/gtPlusPlus/api/recipe/GTPPRecipeMaps.java9
-rw-r--r--src/main/java/gtPlusPlus/api/recipe/TGSFrontend.java132
-rw-r--r--src/main/java/gtPlusPlus/xmod/forestry/HANDLER_FR.java57
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/HANDLER_GT.java2
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java37
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntityTreeFarm.java986
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/loaders/recipe/RecipeLoader_TreeFarm.java718
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/registration/gregtech/GregtechIndustrialTreeFarm.java1
-rw-r--r--src/main/resources/assets/gregtech/lang/en_US.lang2
-rw-r--r--src/main/resources/assets/miscutils/lang/en_US.lang15
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());
+