aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub <53441451+kuba6000@users.noreply.github.com>2023-03-17 19:42:16 +0100
committerGitHub <noreply@github.com>2023-03-17 19:42:16 +0100
commita3831c3c3f3e0c63cc2da3f11b13a75b3aefc303 (patch)
tree32f05ef280f60b6a47eb4d641465e8bdd099d0ca /src
parenta12768cd189fcbca175295a948291a81f8c4d350 (diff)
parenta68f33cc97f38f5d47f2546a688cf1bd12a0bda2 (diff)
downloadGT5-Unofficial-a3831c3c3f3e0c63cc2da3f11b13a75b3aefc303.tar.gz
GT5-Unofficial-a3831c3c3f3e0c63cc2da3f11b13a75b3aefc303.tar.bz2
GT5-Unofficial-a3831c3c3f3e0c63cc2da3f11b13a75b3aefc303.zip
Merge pull request #60 from GTNewHorizons/test
Add Extreme Industrial Greenhouse (moved from BW)
Diffstat (limited to 'src')
-rw-r--r--src/main/java/kubatech/api/LoaderReference.java2
-rw-r--r--src/main/java/kubatech/api/enums/ItemList.java1
-rw-r--r--src/main/java/kubatech/client/effect/CropRenderer.java87
-rw-r--r--src/main/java/kubatech/loaders/RecipeLoader.java29
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java1343
5 files changed, 1461 insertions, 1 deletions
diff --git a/src/main/java/kubatech/api/LoaderReference.java b/src/main/java/kubatech/api/LoaderReference.java
index 16526b2b9e..fc736536bc 100644
--- a/src/main/java/kubatech/api/LoaderReference.java
+++ b/src/main/java/kubatech/api/LoaderReference.java
@@ -18,5 +18,7 @@ public class LoaderReference {
public static final boolean Forestry = Loader.isModLoaded("Forestry");
public static final boolean DraconicEvolution = Loader.isModLoaded("DraconicEvolution");
public static final boolean Avaritia = Loader.isModLoaded("Avaritia");
+ public static final boolean ProjRedIllumination = Loader.isModLoaded("ProjRed|Illumination");
+ public static final boolean RandomThings = Loader.isModLoaded("RandomThings");
public static final boolean BetterLoadingScreen = Loader.isModLoaded("betterloadingscreen");
}
diff --git a/src/main/java/kubatech/api/enums/ItemList.java b/src/main/java/kubatech/api/enums/ItemList.java
index 426cac0df5..55621888ee 100644
--- a/src/main/java/kubatech/api/enums/ItemList.java
+++ b/src/main/java/kubatech/api/enums/ItemList.java
@@ -19,6 +19,7 @@ public enum ItemList implements IItemContainer {
ExtremeExterminationChamber,
ExtremeIndustrialApiary,
+ ExtremeIndustrialGreenhouse,
LegendaryBlackTea,
LegendaryButterflyTea,
LegendaryEarlGrayTea,
diff --git a/src/main/java/kubatech/client/effect/CropRenderer.java b/src/main/java/kubatech/client/effect/CropRenderer.java
new file mode 100644
index 0000000000..e9b6aac3dc
--- /dev/null
+++ b/src/main/java/kubatech/client/effect/CropRenderer.java
@@ -0,0 +1,87 @@
+/*
+ * KubaTech - Gregtech Addon Copyright (C) 2022 - 2023 kuba6000 This library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have
+ * received a copy of the GNU Lesser General Public License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+package kubatech.client.effect;
+
+import java.lang.reflect.Field;
+
+import net.minecraft.client.particle.EntityFX;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.init.Blocks;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.world.World;
+
+import org.lwjgl.opengl.GL11;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+@SideOnly(Side.CLIENT)
+public class CropRenderer extends EntityFX {
+
+ int[] meta = new int[8];
+ static Field tessellatorHasBrightnessField = null;
+
+ public CropRenderer(World world, int x, int y, int z, int age) {
+ super(world, (double) x, ((double) y - 0.0625d), (double) z);
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.particleMaxAge = age;
+ for (int i = 0; i < 8; i++) this.meta[i] = this.rand.nextInt(8);
+ }
+
+ @Override
+ public void onUpdate() {
+ if (this.particleAge++ >= this.particleMaxAge) this.setDead();
+ }
+
+ @Override
+ public void renderParticle(Tessellator p_70539_1_, float p_70539_2_, float p_70539_3_, float p_70539_4_,
+ float p_70539_5_, float p_70539_6_, float p_70539_7_) {
+ Tessellator tessellator = Tessellator.instance;
+ GL11.glDisable(GL11.GL_CULL_FACE);
+ GL11.glDepthMask(false);
+ try {
+ if (tessellatorHasBrightnessField == null) {
+ tessellatorHasBrightnessField = Tessellator.class.getDeclaredField(
+ (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment") ? "hasBrightness"
+ : "field_78414_p");
+ tessellatorHasBrightnessField.setAccessible(true);
+ }
+ tessellatorHasBrightnessField.set(tessellator, false);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ tessellator.setColorRGBA(255, 255, 255, 255);
+ double f12 = this.posY - interpPosY;
+ int i = 0;
+ for (int x = -1; x <= 1; x++) for (int z = -1; z <= 1; z++) {
+ if (x == 0 && z == 0) continue;
+ double f11 = (this.posX + (double) x) - interpPosX;
+ double f13 = (this.posZ + (double) z) - interpPosZ;
+ RenderBlocks.getInstance().renderBlockCropsImpl(Blocks.wheat, meta[i++], f11, f12, f13);
+ }
+
+ GL11.glEnable(GL11.GL_CULL_FACE);
+ GL11.glDepthMask(true);
+ }
+
+ @Override
+ public int getFXLayer() {
+ return 1;
+ }
+
+ @Override
+ public boolean shouldRenderInPass(int pass) {
+ return pass == 2;
+ }
+}
diff --git a/src/main/java/kubatech/loaders/RecipeLoader.java b/src/main/java/kubatech/loaders/RecipeLoader.java
index c8241e7f0c..9437b965a3 100644
--- a/src/main/java/kubatech/loaders/RecipeLoader.java
+++ b/src/main/java/kubatech/loaders/RecipeLoader.java
@@ -18,9 +18,11 @@ import kubatech.Tags;
import kubatech.api.LoaderReference;
import kubatech.api.enums.ItemList;
import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeExterminationChamber;
+import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse;
import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_MegaIndustrialApiary;
import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
@@ -86,6 +88,25 @@ public class RecipeLoader {
6000,
2_048_000);
}
+ if (registerMTEUsingID(
+ 12_792,
+ ExtremeIndustrialGreenhouse,
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse.class,
+ "multimachine.extremegreenhouse",
+ "Extreme Industrial Greenhouse",
+ true /* IC2 is always loaded */)) {
+ GT_ModHandler.addCraftingRecipe(
+ ExtremeIndustrialGreenhouse.get(1),
+ bitsd,
+ new Object[] { "AZA", "BRB", "AZA", 'B', gregtech.api.enums.ItemList.Casing_CleanStainlessSteel,
+ 'R',
+ GT_ModHandler
+ .getModItem("EnderIO", "blockFarmStation", 1, new ItemStack(Items.diamond_hoe)),
+ 'A',
+ LoaderReference.GTNHCoreMod ? CustomItemList.AcceleratorIV.get(1)
+ : gregtech.api.enums.ItemList.Robot_Arm_IV,
+ 'Z', OrePrefixes.circuit.get(Materials.Ultimate) });
+ }
RegisterTeaLine();
if (MTEID > MTEIDMax + 1) throw new RuntimeException("MTE ID's");
}
@@ -108,6 +129,13 @@ public class RecipeLoader {
private static boolean registerMTE(ItemList item, Class<? extends MetaTileEntity> mte, String aName,
String aNameRegional, boolean dep) {
if (MTEID > MTEIDMax) throw new RuntimeException("MTE ID's");
+ registerMTEUsingID(MTEID, item, mte, aName, aNameRegional, dep);
+ MTEID++;
+ return dep;
+ }
+
+ private static boolean registerMTEUsingID(int ID, ItemList item, Class<? extends MetaTileEntity> mte, String aName,
+ String aNameRegional, boolean dep) {
if (dep) {
try {
item.set(
@@ -123,7 +151,6 @@ public class RecipeLoader {
throw new RuntimeException(ex.getMessage());
}
}
- MTEID++;
return dep;
}
diff --git a/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java
new file mode 100644
index 0000000000..8cf0ce802f
--- /dev/null
+++ b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java
@@ -0,0 +1,1343 @@
+/*
+ * KubaTech - Gregtech Addon Copyright (C) 2022 - 2023 kuba6000 This library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have
+ * received a copy of the GNU Lesser General Public License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+package kubatech.tileentity.gregtech.multiblock;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+import static gregtech.api.util.GT_StructureUtility.ofHatchAdder;
+import static kubatech.api.Variables.Author;
+import static kubatech.api.Variables.StructureHologram;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import kubatech.Tags;
+import kubatech.api.LoaderReference;
+import kubatech.api.implementations.KubaTechGTMultiBlockBase;
+import kubatech.api.network.CustomTileEntityPacket;
+import kubatech.api.tileentity.CustomTileEntityPacketHandler;
+import kubatech.client.effect.CropRenderer;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockFlower;
+import net.minecraft.block.BlockStem;
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.InventoryCrafting;
+import net.minecraft.item.*;
+import net.minecraft.item.crafting.CraftingManager;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.IPlantable;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.github.bartimaeusnek.bartworks.API.BorosilicateGlass;
+import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
+import com.gtnewhorizons.modularui.api.drawable.Text;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.math.Pos2d;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.*;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.*;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.GT_DummyWorld;
+import gregtech.common.blocks.GT_Block_Ores_Abstract;
+import gregtech.common.blocks.GT_Item_Ores;
+import gregtech.common.blocks.GT_TileEntity_Ores;
+import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_OutputBus_ME;
+import ic2.api.crops.CropCard;
+import ic2.api.crops.Crops;
+import ic2.core.Ic2Items;
+import ic2.core.crop.TileEntityCrop;
+
+@SuppressWarnings("unused")
+public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse
+ extends KubaTechGTMultiBlockBase<GT_MetaTileEntity_ExtremeIndustrialGreenhouse>
+ implements CustomTileEntityPacketHandler {
+
+ private static final boolean debug = false;
+ private static final int EIG_MATH_VERSION = 0;
+ private static final int CONFIGURATION_WINDOW_ID = 999;
+
+ private int oldVersion = 0;
+ private int mCasing = 0;
+ public int mMaxSlots = 0;
+ private int setupphase = 1;
+ private boolean isIC2Mode = false;
+ private byte glasTier = 0;
+ private int waterusage = 0;
+ private int weedexusage = 0;
+ private boolean isNoHumidity = false;
+ private static final int CASING_INDEX = 49;
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final Item forestryfertilizer = GameRegistry.findItem("Forestry", "fertilizerCompound");
+ private static final Fluid weedex = Materials.WeedEX9000.mFluid;
+ private static final IStructureDefinition<GT_MetaTileEntity_ExtremeIndustrialGreenhouse> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_ExtremeIndustrialGreenhouse>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { "ccccc", "ccccc", "ccccc", "ccccc", "ccccc" },
+ { "ccccc", "clllc", "clllc", "clllc", "ccccc" },
+ { "ggggg", "g---g", "g---g", "g---g", "ggggg" },
+ { "ggggg", "g---g", "g---g", "g---g", "ggggg" },
+ { "ccccc", "cdddc", "cdwdc", "cdddc", "ccccc" },
+ { "cc~cc", "cCCCc", "cCCCc", "cCCCc", "ccccc" }, }))
+ .addElement(
+ 'c',
+ ofChain(
+ onElementPass(t -> t.mCasing++, ofBlock(GregTech_API.sBlockCasings4, 1)),
+ ofHatchAdder(
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse::addEnergyInputToMachineList,
+ CASING_INDEX,
+ 1),
+ ofHatchAdder(
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse::addMaintenanceToMachineList,
+ CASING_INDEX,
+ 1),
+ ofHatchAdder(
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse::addInputToMachineList,
+ CASING_INDEX,
+ 1),
+ ofHatchAdder(
+ GT_MetaTileEntity_ExtremeIndustrialGreenhouse::addOutputToMachineList,
+ CASING_INDEX,
+ 1)))
+ .addElement('C', onElementPass(t -> t.mCasing++, ofBlock(GregTech_API.sBlockCasings4, 1)))
+ .addElement(
+ 'l',
+ LoaderReference.ProjRedIllumination
+ ? ofBlock(Block.getBlockFromName("ProjRed|Illumination:projectred.illumination.lamp"), 10)
+ : ofBlock(Blocks.redstone_lamp, 0))
+ .addElement(
+ 'g',
+ LoaderReference.Bartworks ? BorosilicateGlass.ofBoroGlass(
+ (byte) 0,
+ (byte) 1,
+ Byte.MAX_VALUE,
+ (te, t) -> te.glasTier = t,
+ te -> te.glasTier) : onElementPass(t -> t.glasTier = 100, ofBlock(Blocks.glass, 0)))
+ .addElement(
+ 'd',
+ ofBlock(
+ LoaderReference.RandomThings ? Block.getBlockFromName("RandomThings:fertilizedDirt_tilled")
+ : Blocks.farmland,
+ 0))
+ .addElement('w', ofBlock(Blocks.water, 0)).build();
+
+ public GT_MetaTileEntity_ExtremeIndustrialGreenhouse(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_ExtremeIndustrialGreenhouse(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ if (this.mMaxProgresstime > 0) {
+ GT_Utility.sendChatToPlayer(aPlayer, "You can't change IC2 mode if the machine is working!");
+ return;
+ }
+ if (!mStorage.isEmpty()) {
+ GT_Utility.sendChatToPlayer(aPlayer, "You can't change IC2 mode if there are seeds inside!");
+ return;
+ }
+ this.isIC2Mode = !this.isIC2Mode;
+ GT_Utility.sendChatToPlayer(aPlayer, "IC2 mode is now " + (this.isIC2Mode ? "enabled" : "disabled."));
+ } else {
+ if (this.mMaxProgresstime > 0) {
+ GT_Utility.sendChatToPlayer(aPlayer, "You can't enable/disable setup if the machine is working!");
+ return;
+ }
+ this.setupphase++;
+ if (this.setupphase == 3) this.setupphase = 0;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ "EIG is now running in " + (this.setupphase == 1 ? "setup mode (input)."
+ : (this.setupphase == 2 ? "setup mode (output)." : "normal operation.")));
+ }
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(byte aSide, byte aWrenchingSide, EntityPlayer aPlayer, float aX, float aY,
+ float aZ) {
+ isNoHumidity = !isNoHumidity;
+ GT_Utility.sendChatToPlayer(aPlayer, "Give incoming crops no humidity " + isNoHumidity);
+ return true;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity iGregTechTileEntity) {
+ return new GT_MetaTileEntity_ExtremeIndustrialGreenhouse(this.mName);
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_ExtremeIndustrialGreenhouse> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> d.offsetY == 0 && r.isNotRotated() && f.isNotFlipped();
+ }
+
+ private static String tierString(int tier) {
+ return GT_Values.TIER_COLORS[tier] + GT_Values.VN[tier] + EnumChatFormatting.RESET + EnumChatFormatting.GRAY;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Crop Farm").addInfo("Controller block for the Extreme Industrial Greenhouse").addInfo(Author)
+ .addInfo("Grow your crops like a chad !").addInfo("Use screwdriver to enable/change/disable setup mode")
+ .addInfo("Use screwdriver while sneaking to enable/disable IC2 mode")
+ .addInfo("Use wire cutters to give incoming IC2 crops 0 humidity")
+ .addInfo("Uses 1000L of water per crop per operation")
+ .addInfo("If there are >= 1000 crops -> Uses 1L of Weed-EX 9000 per crop per second")
+ .addInfo("Otherwise, around 1% of crops will die each operation")
+ .addInfo("You can insert fertilizer each operation to get more drops (max +400%)")
+ .addInfo("-------------------- SETUP MODE --------------------").addInfo("Does not take power")
+ .addInfo("There are two modes: input / output")
+ .addInfo("Input mode: machine will take seeds from input bus and plant them")
+ .addInfo("[IC2] You need to also input block that is required under the crop")
+ .addInfo("Output mode: machine will take planted seeds and output them")
+ .addInfo("-------------------- NORMAL CROPS --------------------")
+ .addInfo("Minimal tier: " + tierString(4)).addInfo("Starting with 1 slot")
+ .addInfo("Every slot gives 64 crops")
+ .addInfo("Every tier past " + tierString(4) + ", slots are multiplied by 2")
+ .addInfo("Base process time: 5 sec")
+ .addInfo("Process time is divided by number of tiers past " + tierString(3) + " (Minimum 1 sec)")
+ .addInfo("All crops are grown at the end of the operation")
+ .addInfo("Will automatically craft seeds if they are not dropped")
+ .addInfo("1 Fertilizer per 1 crop +200%")
+ .addInfo("-------------------- IC2 CROPS --------------------")
+ .addInfo("Minimal tier: " + tierString(6)).addInfo("Need " + tierString(6) + " glass tier")
+ .addInfo("Starting with 4 slots").addInfo("Every slot gives 1 crop")
+ .addInfo("Every tier past " + tierString(6) + ", slots are multiplied by 4")
+ .addInfo("Process time: 5 sec").addInfo("All crops are accelerated by x32 times")
+ .addInfo("1 Fertilizer per 1 crop +10%").addInfo(StructureHologram).addSeparator()
+ .beginStructureBlock(5, 6, 5, false).addController("Front bottom center")
+ .addCasingInfo("Clean Stainless Steel Casings", 70)
+ .addOtherStructurePart("Borosilicate Glass", "Hollow two middle layers")
+ .addStructureInfo("The glass tier limits the Energy Input tier")
+ .addStructureInfo("The dirt is from RandomThings, must be tilled")
+ .addStructureInfo("Purple lamps are from ProjectRedIllumination. They can be powered and/or inverted")
+ .addMaintenanceHatch("Any casing (Except inner bottom ones)", 1)
+ .addInputBus("Any casing (Except inner bottom ones)", 1)
+ .addOutputBus("Any casing (Except inner bottom ones)", 1)
+ .addInputHatch("Any casing (Except inner bottom ones)", 1)
+ .addEnergyHatch("Any casing (Except inner bottom ones)", 1).toolTipFinisher(Tags.MODNAME);
+ return tt;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ List<String> info = new ArrayList<>(Arrays.asList(super.getStructureDescription(stackSize)));
+ info.add("The dirt is from RandomThings, must be tilled");
+ info.add("Purple lamps are from ProjectRedIllumination. They can be powered and/or inverted");
+ return info.toArray(new String[] {});
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("EIG_MATH_VERSION", EIG_MATH_VERSION);
+ aNBT.setByte("glasTier", glasTier);
+ aNBT.setInteger("setupphase", setupphase);
+ aNBT.setBoolean("isIC2Mode", isIC2Mode);
+ aNBT.setBoolean("isNoHumidity", isNoHumidity);
+ aNBT.setInteger("mStorageSize", mStorage.size());
+ for (int i = 0; i < mStorage.size(); i++) aNBT.setTag("mStorage." + i, mStorage.get(i).toNBTTagCompound());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ oldVersion = aNBT.hasKey("EIG_MATH_VERSION") ? aNBT.getInteger("EIG_MATH_VERSION") : -1;
+ glasTier = aNBT.getByte("glasTier");
+ setupphase = aNBT.getInteger("setupphase");
+ isIC2Mode = aNBT.getBoolean("isIC2Mode");
+ isNoHumidity = aNBT.getBoolean("isNoHumidity");
+ for (int i = 0; i < aNBT.getInteger("mStorageSize"); i++)
+ mStorage.add(new GreenHouseSlot(aNBT.getCompoundTag("mStorage." + i)));
+ }
+
+ @SideOnly(Side.CLIENT)
+ public void spawnVisualCrops(World world, int x, int y, int z, int age) {
+ CropRenderer crop = new CropRenderer(world, x, y, z, age);
+ Minecraft.getMinecraft().effectRenderer.addEffect(crop);
+ }
+
+ private CustomTileEntityPacket packet = null;
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isClientSide()) {
+ if (aBaseMetaTileEntity.isActive() && aTick % 40 == 0) {
+ int[] abc = new int[] { 0, -2, 2 };
+ int[] xyz = new int[] { 0, 0, 0 };
+ this.getExtendedFacing().getWorldOffset(abc, xyz);
+ xyz[0] += aBaseMetaTileEntity.getXCoord();
+ xyz[1] += aBaseMetaTileEntity.getYCoord();
+ xyz[2] += aBaseMetaTileEntity.getZCoord();
+ spawnVisualCrops(aBaseMetaTileEntity.getWorld(), xyz[0], xyz[1], xyz[2], 40);
+ }
+ }
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (packet == null) packet = new CustomTileEntityPacket((TileEntity) aBaseMetaTileEntity, null);
+ packet.resetHelperData();
+ packet.addData(mMaxSlots);
+ packet.sendToAllAround(20);
+ }
+ }
+
+ @Override
+ public void HandleCustomPacket(CustomTileEntityPacket customdata) {
+ mMaxSlots = customdata.getDataInt();
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean b) {
+ buildPiece(STRUCTURE_PIECE_MAIN, itemStack, b, 2, 5, 0);
+ }
+
+ private void updateMaxSlots() {
+ long v = this.getMaxInputVoltage();
+ int tier = GT_Utility.getTier(v);
+ if (tier < (isIC2Mode ? 6 : 4)) mMaxSlots = 0;
+ else if (isIC2Mode) mMaxSlots = 4 << (2 * (tier - 6));
+ else mMaxSlots = 1 << (tier - 4);
+ }
+
+ @Override
+ public boolean checkRecipe(ItemStack itemStack) {
+ long v = this.getMaxInputVoltage();
+ int tier = GT_Utility.getTier(v);
+ updateMaxSlots();
+
+ if (oldVersion != EIG_MATH_VERSION) {
+ for (GreenHouseSlot slot : mStorage) slot.recalculate(this, getBaseMetaTileEntity().getWorld());
+ oldVersion = EIG_MATH_VERSION;
+ }
+
+ if (setupphase > 0) {
+ if ((mStorage.size() >= mMaxSlots && setupphase == 1) || (mStorage.size() == 0 && setupphase == 2))
+ return false;
+
+ if (setupphase == 1) {
+ List<ItemStack> inputs = getStoredInputs();
+ for (ItemStack input : inputs) {
+ addCrop(input);
+ if (mStorage.size() >= mMaxSlots) break;
+ }
+ } else if (setupphase == 2) {
+ int emptySlots = 0;
+ boolean ignoreEmptiness = false;
+ for (GT_MetaTileEntity_Hatch_OutputBus i : mOutputBusses) {
+ if (i instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) {
+ ignoreEmptiness = true;
+ break;
+ }
+ for (int j = 0; j < i.getSizeInventory(); j++)
+ if (i.isValidSlot(j)) if (i.getStackInSlot(j) == null) emptySlots++;
+ }
+ while (mStorage.size() > 0) {
+ if (!ignoreEmptiness && (emptySlots -= 2) < 0) break;
+ this.addOutput(this.mStorage.get(0).input.copy());
+ if (this.mStorage.get(0).undercrop != null) this.addOutput(this.mStorage.get(0).undercrop.copy());
+ this.mStorage.remove(0);
+ }
+ }
+
+ this.updateSlots();
+ this.mMaxProgresstime = 5;
+ this.mEUt = 0;
+ this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ this.mEfficiencyIncrease = 10000;
+ return true;
+ }
+ if (mStorage.size() > mMaxSlots) return false;
+ if (mStorage.isEmpty()) return false;
+
+ waterusage = 0;
+ weedexusage = 0;
+ for (GreenHouseSlot s : mStorage) waterusage += s.input.stackSize;
+ if (waterusage >= 1000) weedexusage = waterusage;
+ waterusage *= 1000;
+
+ List<GT_MetaTileEntity_Hatch_Input> fluids = mInputHatches;
+ List<GT_MetaTileEntity_Hatch_Input> fluidsToUse = new ArrayList<>(fluids.size());
+ int watercheck = waterusage;
+ FluidStack waterStack = new FluidStack(FluidRegistry.WATER, 1);
+ for (GT_MetaTileEntity_Hatch_Input i : fluids) {
+ if (!isValidMetaTileEntity(i)) continue;
+ if (i instanceof GT_MetaTileEntity_Hatch_MultiInput) {
+ int amount = ((GT_MetaTileEntity_Hatch_MultiInput) i).getFluidAmount(waterStack);
+ if (amount == 0) continue;
+ watercheck -= amount;
+ } else {
+ FluidStack stack = i.getDrainableStack();
+ if (stack == null) continue;
+ if (!stack.isFluidEqual(waterStack)) continue;
+ if (stack.amount <= 0) continue;
+ watercheck -= stack.amount;
+ }
+ fluidsToUse.add(i);
+ if (watercheck <= 0) break;
+ }
+ if (watercheck > 0 && !debug) return false;
+ watercheck = waterusage;
+ for (GT_MetaTileEntity_Hatch_Input i : fluidsToUse) {
+ int used = i.drain(watercheck, true).amount;
+ watercheck -= used;
+ }
+
+ // weedex
+ if (weedexusage > 0 && !this.depleteInput(new FluidStack(weedex, isIC2Mode ? weedexusage * 5 : weedexusage))) {
+ IGregTechTileEntity baseMTE = this.getBaseMetaTileEntity();
+ int tokill = baseMTE.getRandomNumber((int) ((double) weedexusage * 0.02d) + 1);
+ for (int i = 0; i < tokill;) {
+ GreenHouseSlot removed = mStorage.remove(baseMTE.getRandomNumber(mStorage.size()));
+ i -= removed.input.stackSize;
+ }
+ }
+
+ // OVERCLOCK
+ // FERTILIZER IDEA:
+ // IC2 +10% per fertilizer per crop per operation
+ // NORMAL +200% per fertilizer per crop per operation
+
+ int boost = 0;
+ int maxboost = 0;
+ for (GreenHouseSlot s : mStorage) maxboost += s.input.stackSize * (isIC2Mode ? 40 : 2);
+
+ ArrayList<ItemStack> inputs = getStoredInputs();
+ for (ItemStack i : inputs) {
+ if ((i.getItem() == Items.dye && i.getItemDamage() == 15)
+ || (forestryfertilizer != null && (i.getItem() == forestryfertilizer))
+ || (GT_Utility.areStacksEqual(i, Ic2Items.fertilizer))) {
+ int used = Math.min(i.stackSize, maxboost - boost);
+ i.stackSize -= used;
+ boost += used;
+ }
+ if (boost == maxboost) break;
+ }
+
+ double multiplier = 1.d + (((double) boost / (double) maxboost) * 4d);
+
+ if (isIC2Mode) {
+ if (glasTier < 6) return false;
+ this.mMaxProgresstime = 100;
+ List<ItemStack> outputs = new ArrayList<>();
+ for (int i = 0; i < Math.min(mMaxSlots, mStorage.size()); i++)
+ outputs.addAll(mStorage.get(i).getIC2Drops(((double) this.mMaxProgresstime * 32d) * multiplier));
+ this.mOutputItems = outputs.toArray(new ItemStack[0]);
+ } else {
+ this.mMaxProgresstime = Math.max(20, 100 / (tier - 3)); // Min 1 s
+ List<ItemStack> outputs = new ArrayList<>();
+ for (int i = 0; i < Math.min(mMaxSlots, mStorage.size()); i++) {
+ for (ItemStack drop : mStorage.get(i).getDrops()) {
+ ItemStack s = drop.copy();
+ s.stackSize = (int) ((double) s.stackSize * multiplier);
+ outputs.add(s);
+ }
+ }
+ this.mOutputItems = outputs.toArray(new ItemStack[0]);
+ }
+ this.mEUt = -(int) ((double) GT_Values.V[tier] * 0.99d);
+ this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ this.mEfficiencyIncrease = 10000;
+ this.updateSlots();
+ return true;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) {
+ mCasing = 0;
+ glasTier = 0;
+ if (debug) glasTier = 8;
+
+ if (!checkPiece(STRUCTURE_PIECE_MAIN, 2, 5, 0)) return false;
+
+ if (this.glasTier < 8 && !this.mEnergyHatches.isEmpty())
+ for (GT_MetaTileEntity_Hatch_Energy hatchEnergy : this.mEnergyHatches)
+ if (this.glasTier < hatchEnergy.mTier) return false;
+
+ boolean valid = this.mMaintenanceHatches.size() == 1 && this.mEnergyHatches.size() >= 1 && this.mCasing >= 70;
+
+ if (valid) updateMaxSlots();
+
+ return valid;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public int getGUIHeight() {
+ return 166;
+ }
+
+ @Override
+ public int getGUIWidth() {
+ return 176;
+ }
+
+ @Override
+ public void bindPlayerInventoryUI(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.bindPlayerInventory(buildContext.getPlayer(), new Pos2d(7, 83), this.getGUITextureSet().getItemSlot());
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK).setPos(7, 4).setSize(143, 75)
+ .setEnabled(widget -> !isFixed.apply(widget)));
+
+ buildContext.addSyncedWindow(CONFIGURATION_WINDOW_ID, this::createConfigurationWindow);
+ EntityPlayer player = buildContext.getPlayer();
+
+ // Slot is not needed
+
+ builder.widget(
+ new DynamicPositionedColumn().setSynced(false).widget(
+ new CycleButtonWidget().setToggle(() -> getBaseMetaTileEntity().isAllowedToWork(), works -> {
+ if (works) getBaseMetaTileEntity().enableWorking();
+ else getBaseMetaTileEntity().disableWorking();
+
+ if (!(player instanceof EntityPlayerMP)) return;
+ String tChat = GT_Utility.trans("090", "Machine Processing: ")
+ + (works ? GT_Utility.trans("088", "Enabled")
+ : GT_Utility.trans("087", "Disabled"));
+ if (hasAlternativeModeText()) tChat = getAlternativeModeText();
+ GT_Utility.sendChatToPlayer(player, tChat);
+ }).addTooltip(0, new Text("Disabled").color(Color.RED.dark(3)))
+ .addTooltip(1, new Text("Enabled").color(Color.GREEN.dark(3)))
+ .setVariableBackgroundGetter(toggleButtonBackgroundGetter).setSize(18, 18)
+ .addTooltip("Working status"))
+ .widget(
+ new ButtonWidget()
+ .setOnClick(
+ (clickData, widget) -> {
+ if (!widget.isClient())
+ widget.getContext().openSyncedWindow(CONFIGURATION_WINDOW_ID);
+ })
+ .setBackground(
+ GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_CYCLIC)
+ .addTooltip("Configuration").setSize(18, 18))
+ .setPos(151, 4));
+
+ final List<ItemStack> drawables = new ArrayList<>(mMaxSlots);
+ final int perRow = 7;
+
+ Scrollable cropsContainer = new Scrollable().setVerticalScroll();
+
+ if (mMaxSlots > 0) for (int i = 0, imax = ((mMaxSlots - 1) / perRow); i <= imax; i++) {
+ DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false);
+ for (int j = 0, jmax = (i == imax ? (mMaxSlots - 1) % perRow : (perRow - 1)); j <= jmax; j++) {
+ final int finalI = i * perRow;
+ final int finalJ = j;
+ final int ID = finalI + finalJ;
+ row.widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ if (!(player instanceof EntityPlayerMP)) return;
+ if (mStorage.size() <= ID) return;
+ if (this.mMaxProgresstime > 0) {
+ GT_Utility.sendChatToPlayer(player, "Can't eject while running !");
+ return;
+ }
+ GreenHouseSlot removed = mStorage.remove(ID);
+ addOutput(removed.input);
+ GT_Utility.sendChatToPlayer(player, "Crop ejected !");
+ }).setBackground(
+ () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet().getItemSlot(),
+ new ItemDrawable(drawables.size() > ID ? drawables.get(ID) : null)
+ .withFixedSize(16, 16, 1, 1) })
+ .dynamicTooltip(() -> {
+ if (drawables.size() > ID) return Arrays.asList(
+ drawables.get(ID).getDisplayName(),
+ "Amount: " + drawables.get(ID).stackSize,
+ EnumChatFormatting.GRAY + "Left click to eject");
+ return Collections.emptyList();
+ }).setSize(18, 18));
+ }
+ cropsContainer.widget(row.setPos(0, i * 18));
+ }
+ cropsContainer.attachSyncer(
+ new FakeSyncWidget.ListSyncer<>(
+ () -> mStorage.stream().map(s -> s.input).collect(Collectors.toList()),
+ l -> {
+ drawables.clear();
+ drawables.addAll(l);
+ },
+ (buffer, i) -> {
+ try {
+ buffer.writeItemStackToBuffer(i);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ },
+ buffer -> {
+ try {
+ return buffer.readItemStackFromBuffer();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }),
+ builder);
+
+ builder.widget(cropsContainer.setPos(10, 16).setSize(128, 60));
+
+ final DynamicPositionedColumn screenElements = new DynamicPositionedColumn();
+ drawTexts(screenElements, null);
+ builder.widget(screenElements);
+ }
+
+ protected ModularWindow createConfigurationWindow(final EntityPlayer player) {
+ ModularWindow.Builder builder = ModularWindow.builder(200, 100);
+ builder.setBackground(ModularUITextures.VANILLA_BACKGROUND);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CYCLIC).setPos(5, 5).setSize(16, 16))
+ .widget(new TextWidget("Configuration").setPos(25, 9))
+ .widget(ButtonWidget.closeWindowButton(true).setPos(185, 3))
+ .widget(
+ new Column().widget(
+ new CycleButtonWidget().setLength(3).setGetter(() -> setupphase).setSetter(val -> {
+ if (!(player instanceof EntityPlayerMP)) return;
+ if (this.mMaxProgresstime > 0) {
+ GT_Utility.sendChatToPlayer(
+ player,
+ "You can't enable/disable setup if the machine is working!");
+ return;
+ }
+ this.setupphase = val;
+ GT_Utility.sendChatToPlayer(
+ player,
+ "EIG is now running in " + (this.setupphase == 1 ? "setup mode (input)."
+ : (this.setupphase == 2 ? "setup mode (output)."
+ : "normal operation.")));
+ }).addTooltip(0, new Text("Operating").color(Color.GREEN.dark(3)))
+ .addTooltip(1, new Text("Input").color(Color.YELLOW.dark(3)))
+ .addTooltip(2, new Text("Output").color(Color.YELLOW.dark(3)))
+ .setVariableBackgroundGetter(
+ i -> new IDrawable[] { ModularUITextures.VANILLA_BACKGROUND,
+ GT_UITextures.OVERLAY_BUTTON_CYCLIC.withFixedSize(18, 18),
+ i == 0 ? new Text("Operating").color(Color.GREEN.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0)
+ : i == 1 ? new Text("Input").color(Color.YELLOW.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0)
+ : new Text("Output").color(Color.YELLOW.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0) })
+ .setSize(70, 18).addTooltip("Setup mode"))
+ .widget(
+ new CycleButtonWidget().setLength(2).setGetter(() -> isIC2Mode ? 1 : 0)
+ .setSetter(val -> {
+ if (!(player instanceof EntityPlayerMP)) return;
+ if (this.mMaxProgresstime > 0) {
+ GT_Utility.sendChatToPlayer(
+ player,
+ "You can't change IC2 mode if the machine is working!");
+ return;
+ }
+ if (!mStorage.isEmpty()) {
+ GT_Utility.sendChatToPlayer(
+ player,
+ "You can't change IC2 mode if there are seeds inside!");
+ return;
+ }
+ this.isIC2Mode = val == 1;
+ GT_Utility.sendChatToPlayer(
+ player,
+ "IC2 mode is now "
+ + (this.isIC2Mode ? "enabled" : "disabled."));
+ }).addTooltip(0, new Text("Disabled").color(Color.RED.dark(3)))
+ .addTooltip(1, new Text("Enabled").color(Color.GREEN.dark(3)))
+ .setVariableBackgroundGetter(
+ i -> new IDrawable[] { ModularUITextures.VANILLA_BACKGROUND,
+ GT_UITextures.OVERLAY_BUTTON_CYCLIC
+ .withFixedSize(18, 18),
+ i == 0 ? new Text("Disabled").color(Color.RED.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0)
+ : new Text("Enabled").color(Color.GREEN.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0) })
+ .setSize(70, 18).addTooltip("IC2 mode"))
+ .widget(
+ new CycleButtonWidget().setLength(2).setGetter(() -> isNoHumidity ? 1 : 0)
+ .setSetter(val -> {
+ if (!(player instanceof EntityPlayerMP)) return;
+ isNoHumidity = val == 1;
+ GT_Utility.sendChatToPlayer(
+ player,
+ "Give incoming crops no humidity " + isNoHumidity);
+ }).addTooltip(0, new Text("Disabled").color(Color.RED.dark(3)))
+ .addTooltip(1, new Text("Enabled").color(Color.GREEN.dark(3)))
+ .setVariableBackgroundGetter(
+ i -> new IDrawable[] { ModularUITextures.VANILLA_BACKGROUND,
+ GT_UITextures.OVERLAY_BUTTON_CYCLIC
+ .withFixedSize(18, 18),
+ i == 0 ? new Text("Disabled").color(Color.RED.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0)
+ : new Text("Enabled").color(Color.GREEN.dark(3))
+ .withFixedSize(70 - 18, 18, 15, 0) })
+ .setSize(70, 18).addTooltip("No Humidity mode"))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()).setPos(10, 30))
+ .widget(
+ new Column().widget(new TextWidget("Setup mode").setSize(100, 18))
+ .widget(new TextWidget("IC2 mode").setSize(100, 18))
+ .widget(new TextWidget("No Humidity mode").setSize(100, 18))
+ .setEnabled(widget -> !getBaseMetaTileEntity().isActive()).setPos(80, 30))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.OVERLAY_BUTTON_CROSS).setSize(18, 18)
+ .setPos(10, 30)
+ .addTooltip(
+ new Text("Can't change configuration when running !").color(Color.RED.dark(3)))
+ .setEnabled(widget -> getBaseMetaTileEntity().isActive()));
+ return builder.build();
+ }
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ screenElements.setSynced(false).setSpace(0).setPos(10, 7);
+
+ screenElements.widget(
+ new DynamicPositionedRow().setSynced(false)
+ .widget(new TextWidget("Status: ").setDefaultColor(COLOR_TEXT_GRAY.get()))
+ .widget(new DynamicTextWidget(() -> {
+ if (getBaseMetaTileEntity().isActive())
+ return new Text("Working !").color(Color.GREEN.dark(3));
+ else if (getBaseMetaTileEntity().isAllowedToWork())
+ return new Text("Enabled").color(Color.GREEN.dark(3));
+ else if (getBaseMetaTileEntity().wasShutdown())
+ return new Text("Shutdown (CRITICAL)").color(Color.RED.dark(3));
+ else return new Text("Disabled").color(Color.RED.dark(3));
+ })).setEnabled(isFixed));
+
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("132", "Pipe is loose."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mWrench))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mWrench, val -> mWrench = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("133", "Screws are loose."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mScrewdriver))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mScrewdriver, val -> mScrewdriver = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("134", "Something is stuck."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mSoftHammer))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mSoftHammer, val -> mSoftHammer = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("135", "Platings are dented."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mHardHammer))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mHardHammer, val -> mHardHammer = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("136", "Circuitry burned out."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mSolderingTool))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mSolderingTool, val -> mSolderingTool = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("137", "That doesn't belong there."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mCrowbar))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mCrowbar, val -> mCrowbar = val));
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("138", "Incomplete Structure."))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()).setEnabled(widget -> !mMachine))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mMachine, val -> mMachine = val));
+ }
+
+ @Override
+ public String[] getInfoData() {
+ List<String> info = new ArrayList<>(
+ Arrays.asList(
+ "Running in mode: " + EnumChatFormatting.GREEN
+ + (setupphase == 0 ? (isIC2Mode ? "IC2 crops" : "Normal crops")
+ : ("Setup mode " + (setupphase == 1 ? "(input)" : "(output)")))
+ + EnumChatFormatting.RESET,
+ "Uses " + waterusage + "L/operation of water",
+ "Uses " + weedexusage + "L/second of Weed-EX 9000",
+ "Max slots: " + EnumChatFormatting.GREEN + this.mMaxSlots + EnumChatFormatting.RESET,
+ "Used slots: "
+ + ((mStorage.size() > mMaxSlots) ? EnumChatFormatting.RED : EnumChatFormatting.GREEN)
+ + this.mStorage.size()
+ + EnumChatFormatting.RESET));
+ HashMap<String, Integer> storageList = new HashMap<>();
+ for (GreenHouseSlot greenHouseSlot : mStorage) {
+ if (!greenHouseSlot.isValid) continue;
+ StringBuilder a = new StringBuilder(
+ EnumChatFormatting.GREEN + "x"
+ + greenHouseSlot.input.stackSize
+ + " "
+ + greenHouseSlot.input.getDisplayName());
+ if (this.isIC2Mode) {
+ a.append(" | Humidity: ").append(greenHouseSlot.noHumidity ? 0 : 12);
+ }
+ a.append(EnumChatFormatting.RESET);
+ storageList.merge(a.toString(), 1, Integer::sum);
+ }
+ storageList.forEach((k, v) -> info.add("x" + v + " " + k));
+ if (mStorage.size() > mMaxSlots) info.add(
+ EnumChatFormatting.DARK_RED + "There are too many crops inside to run !" + EnumChatFormatting.RESET);
+ info.addAll(Arrays.asList(super.getInfoData()));
+ return info.toArray(new String[0]);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, byte aSide, byte aFacing, byte aColorIndex,
+ boolean aActive, boolean aRedstone) {
+ if (aSide == aFacing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX),
+ TextureFactory.builder().addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE).extFacing().build(),
+ TextureFactory.builder().addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_ACTIVE_GLOW).extFacing().glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX),
+ TextureFactory.builder().addIcon(OVERLAY_FRONT_DISTILLATION_TOWER).extFacing().build(),
+ TextureFactory.builder().addIcon(OVERLAY_FRONT_DISTILLATION_TOWER_GLOW).extFacing().glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX) };
+ }
+
+ public final List<GreenHouseSlot> mStorage = new ArrayList<>();
+
+ public boolean addCrop(ItemStack input) {
+ if (!isIC2Mode)
+ for (GreenHouseSlot g : mStorage) if (g.input.stackSize < 64 && GT_Utility.areStacksEqual(g.input, input)) {
+ g.addAll(this.getBaseMetaTileEntity().getWorld(), input);
+ if (input.stackSize == 0) return true;
+ }
+ GreenHouseSlot h = new GreenHouseSlot(this, input, isIC2Mode, isNoHumidity);
+ if (h.isValid) {
+ mStorage.add(h);
+ return true;
+ }
+ return false;
+ }
+
+ private static class GreenHouseSlot extends InventoryCrafting {
+
+ final ItemStack input;
+ Block crop;
+ ArrayList<ItemStack> customDrops = null;
+ ItemStack undercrop = null;
+ List<ItemStack> drops;
+ boolean isValid;
+ boolean isIC2Crop;
+ boolean noHumidity;
+ int growthticks;
+ List<List<ItemStack>> generations;
+
+ Random rn;
+ IRecipe recipe;
+ ItemStack recipeInput;
+
+ int optimalgrowth = 7;
+
+ boolean needsreplanting = true;
+
+ static final GreenHouseWorld fakeworld = new GreenHouseWorld(5, 5, 5);
+
+ public NBTTagCompound toNBTTagCompound() {
+ NBTTagCompound aNBT = new NBTTagCompound();
+ aNBT.setTag("input", input.writeToNBT(new NBTTagCompound()));
+ aNBT.setBoolean("isValid", isValid);
+ aNBT.setBoolean("isIC2Crop", isIC2Crop);
+ if (!isIC2Crop) {
+ aNBT.setInteger("crop", Block.getIdFromBlock(crop));
+ if (customDrops != null && customDrops.size() > 0) {
+ aNBT.setInteger("customDropsCount", customDrops.size());
+ for (int i = 0; i < customDrops.size(); i++)
+ aNBT.setTag("customDrop." + i, customDrops.get(i).writeToNBT(new NBTTagCompound()));
+ }
+ aNBT.setInteger("dropscount", drops.size());
+ for (int i = 0; i < drops.size(); i++)
+ aNBT.setTag("drop." + i, drops.get(i).writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger("optimalgrowth", optimalgrowth);
+ aNBT.setBoolean("needsreplanting", needsreplanting);
+ } else {
+ if (undercrop != null) aNBT.setTag("undercrop", undercrop.writeToNBT(new NBTTagCompound()));
+ aNBT.setInteger("generationscount", generations.size());
+ for (int i = 0; i < generations.size(); i++) {
+ aNBT.setInteger("generation." + i + ".count", generations.get(i).size());
+ for (int j = 0; j < generations.get(i).size(); j++) aNBT.setTag(
+ "generation." + i + "." + j,
+ generations.get(i).get(j).writeToNBT(new NBTTagCompound()));
+ }
+ aNBT.setInteger("growthticks", growthticks);
+ aNBT.setBoolean("noHumidity", noHumidity);
+ }
+ return aNBT;
+ }
+
+ public GreenHouseSlot(NBTTagCompound aNBT) {
+ super(null, 3, 3);
+ isIC2Crop = aNBT.getBoolean("isIC2Crop");
+ isValid = aNBT.getBoolean("isValid");
+ input = ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("input"));
+ if (!isIC2Crop) {
+ crop = Block.getBlockById(aNBT.getInteger("crop"));
+ if (aNBT.hasKey("customDropsCount")) {
+ int imax = aNBT.getInteger("customDropsCount");
+ customDrops = new ArrayList<>(imax);
+ for (int i = 0; i < imax; i++)
+ customDrops.add(ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("customDrop." + i)));
+ }
+ drops = new ArrayList<>();
+ for (int i = 0; i < aNBT.getInteger("dropscount"); i++)
+ drops.add(ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("drop." + i)));
+ optimalgrowth = aNBT.getInteger("optimalgrowth");
+ if (optimalgrowth == 0) optimalgrowth = 7;
+ if (aNBT.hasKey("needsreplanting")) needsreplanting = aNBT.getBoolean("needsreplanting");
+ } else {
+ if (aNBT.hasKey("undercrop"))
+ undercrop = ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("undercrop"));
+ generations = new ArrayList<>();
+ for (int i = 0; i < aNBT.getInteger("generationscount"); i++) {
+ generations.add(new ArrayList<>());
+ for (int j = 0; j < aNBT.getInteger("generation." + i + ".count"); j++) generations.get(i)
+ .add(ItemStack.loadItemStackFromNBT(aNBT.getCompoundTag("generation." + i + "." + j)));
+ }
+ growthticks = aNBT.getInteger("growthticks");
+ noHumidity = aNBT.getBoolean("noHumidity");
+ rn = new Random();
+ }
+ }
+
+ public boolean addAll(World world, ItemStack input) {
+ if (!GT_Utility.areStacksEqual(this.input, input)) return false;
+ if (this.input.stackSize == 64) return false;
+ int toconsume = Math.min(64 - this.input.stackSize, input.stackSize);
+ int left = addDrops(world, toconsume);
+ input.stackSize -= toconsume - left;
+ this.input.stackSize += toconsume - left;
+ return left == 0;
+ }
+
+ public boolean findCropRecipe(World world) {
+ if (recipe != null) return true;
+ out: for (ItemStack drop : drops) {
+ recipeInput = drop;
+ for (int j = 0; j < CraftingManager.getInstance().getRecipeList().size(); j++) {
+ recipe = (IRecipe) CraftingManager.getInstance().getRecipeList().get(j);
+ if (recipe.matches(this, world)
+ && GT_Utility.areStacksEqual(recipe.getCraftingResult(this), input)) {
+ break out;
+ } else recipe = null;
+ }
+ }
+ return recipe != null;
+ }
+
+ @Override
+ public ItemStack getStackInSlot(int p_70301_1_) {
+ if (p_70301_1_ == 0) return recipeInput.copy();
+ return null;
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ return null;
+ }
+
+ @Override
+ public ItemStack decrStackSize(int par1, int par2) {
+ return null;
+ }
+
+ @SuppressWarnings("EmptyMethod")
+ @Override
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {}
+
+ public GreenHouseSlot(GT_MetaTileEntity_ExtremeIndustrialGreenhouse tileEntity, ItemStack input, boolean IC2,
+ boolean noHumidity) {
+ super(null, 3, 3);
+ World world = tileEntity.getBaseMetaTileEntity().getWorld();
+ this.input = input.copy();
+ this.isValid = false;
+ if (IC2) {
+ GreenHouseSlotIC2(tileEntity, world, input, noHumidity);
+ return;
+ }
+ Item i = input.getItem();
+ Block b = null;
+ boolean detectedCustomHandler = false;
+ // Custom handlers
+ // FLOWERS //
+ Block bb = Block.getBlockFromItem(i);
+ if (bb == Blocks.air) bb = null;
+ if (bb instanceof BlockFlower) {
+ detectedCustomHandler = true;
+ needsreplanting = false;
+ customDrops = new ArrayList<>(Collections.singletonList(input.copy()));
+ customDrops.get(0).stackSize = 1;
+ }
+ if (!detectedCustomHandler) {
+ if (i instanceof IPlantable) {
+ if (i instanceof ItemSeeds) b = ((ItemSeeds) i).getPlant(world, 0, 0, 0);
+ else if (i instanceof ItemSeedFood) b = ((ItemSeedFood) i).getPlant(world, 0, 0, 0);
+ } else {
+ if (i == Items.reeds) b = Blocks.reeds;
+ else {
+ b = Block.getBlockFromItem(i);
+ if (b != Blocks.cactus) return;
+ }
+ needsreplanting = false;
+ }
+ if (!(b instanceof IPlantable)) return;
+ GameRegistry.UniqueIdentifier u = GameRegistry.findUniqueIdentifierFor(i);
+ if (u != null && Objects.equals(u.modId, "Natura")) optimalgrowth = 8;
+
+ if (b instanceof BlockStem) {
+ fakeworld.block = null;
+ try {
+ b.updateTick(fakeworld, 5, 5, 5, fakeworld.rand);
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ }
+ if (fakeworld.block == null) return;
+ b = fakeworld.block;
+ needsreplanting = false;
+ }
+ }
+ crop = b;
+ isIC2Crop = false;
+ int toUse = Math.min(64, input.stackSize);
+ if (addDrops(world, toUse) == 0 && !drops.isEmpty()) {
+ input.stackSize -= toUse;
+ this.input.stackSize = toUse;
+ this.isValid = true;
+ }
+ }
+
+ public void GreenHouseSlotIC2(GT_MetaTileEntity_ExtremeIndustrialGreenhouse tileEntity, World world,
+ ItemStack input, boolean noHumidity) {
+ if (!ItemList.IC2_Crop_Seeds.isStackEqual(input, true, true)) return;
+ this.isIC2Crop = true;
+ this.noHumidity = noHumidity;
+ recalculate(tileEntity, world);
+ if (this.isValid) input.stackSize--;
+ }
+
+ private boolean setBlock(ItemStack a, int x, int y, int z, World world) {
+ Item item = a.getItem();
+ Block b = Block.getBlockFromItem(item);
+ if (b == Blocks.air || !(item instanceof ItemBlock)) return false;
+ short tDamage = (short) item.getDamage(a);
+ if (item instanceof GT_Item_Ores && tDamage > 0) {
+ if (!world.setBlock(
+ x,
+ y,
+ z,
+ b,
+ GT_TileEntity_Ores.getHarvestData(
+ tDamage,
+ ((GT_Block_Ores_Abstract) b).getBaseBlockHarvestLevel(tDamage % 16000 / 1000)),
+ 0)) {
+ return false;
+ }
+ GT_TileEntity_Ores tTileEntity = (GT_TileEntity_Ores) world.getTileEntity(x, y, z);
+ tTileEntity.mMetaData = tDamage;
+ tTileEntity.mNatural = false;
+ } else world.setBlock(x, y, z, b, tDamage, 0);
+ return true;
+ }
+
+ public void recalculate(GT_MetaTileEntity_ExtremeIndustrialGreenhouse tileEntity, World world) {
+ if (isIC2Crop) {
+ CropCard cc = Crops.instance.getCropCard(input);
+ this.input.stackSize = 1;
+ NBTTagCompound nbt = input.getTagCompound();
+ byte gr = nbt.getByte("growth");
+ byte ga = nbt.getByte("gain");
+ byte re = nbt.getByte("resistance");
+ int[] abc = new int[] { 0, -2, 3 };
+ int[] xyz = new int[] { 0, 0, 0 };
+ tileEntity.getExtendedFacing().getWorldOffset(abc, xyz);
+ xyz[0] += tileEntity.getBaseMetaTileEntity().getXCoord();
+ xyz[1] += tileEntity.getBaseMetaTileEntity().getYCoord();
+ xyz[2] += tileEntity.getBaseMetaTileEntity().getZCoord();
+ boolean cheating = false;
+ try {
+ if (world.getBlock(xyz[0], xyz[1] - 2, xyz[2]) != GregTech_API.sBlockCasings4
+ || world.getBlockMetadata(xyz[0], xyz[1] - 2, xyz[2]) != 1) {
+ // no
+ cheating = true;
+ return;
+ }
+
+ world.setBlock(xyz[0], xyz[1], xyz[2], Block.getBlockFromItem(Ic2Items.crop.getItem()), 0, 0);
+ TileEntity wte = world.getTileEntity(xyz[0], xyz[1], xyz[2]);
+ if (!(wte instanceof TileEntityCrop)) {
+ // should not be even possible
+ return;
+ }
+ TileEntityCrop te = (TileEntityCrop) wte;
+ te.ticker = 1; // don't even think about ticking once
+ te.setCrop(cc);
+
+ te.setGrowth(gr);
+ te.setGain(ga);
+ te.setResistance(re);
+
+ ItemStack tobeused = null;
+
+ if (undercrop != null) setBlock(undercrop, xyz[0], xyz[1] - 2, xyz[2], world);
+ else {
+ te.setSize((byte) (cc.maxSize() - 1));
+ if (!cc.canGrow(te)) {
+ // needs special block
+
+ boolean cangrow = false;
+ ArrayList<ItemStack> inputs = tileEntity.getStoredInputs();
+ for (ItemStack a : inputs) {
+ if (a.stackSize <= 0) continue;
+ if (!setBlock(a, xyz[0], xyz[1] - 2, xyz[2], world)) continue;
+ if (!cc.canGrow(te)) continue;
+ cangrow = true;
+ undercrop = a.copy();
+ undercrop.stackSize = 1;
+ tobeused = a;
+ break;
+ }
+
+ if (!cangrow) return;
+ }
+ }
+
+ te.setSize((byte) cc.maxSize());
+
+ if (!cc.canBeHarvested(te)) return;
+
+ // GENERATE DROPS
+ generations = new ArrayList<>();
+ out: for (int i = 0; i < 10; i++) // get 10 generations
+ {
+ ItemStack[] st = te.harvest_automated(false);
+ te.setSize((byte) cc.maxSize());
+ if (st == null) continue;
+ if (st.length == 0) continue;
+ for (ItemStack s : st) if (s == null) continue out;
+ generations.add(new ArrayList<>(Arrays.asList(st)));
+ }
+ if (generations.isEmpty()) return;
+ rn = new Random();
+
+ // CHECK GROWTH SPEED
+ te.humidity = (byte) (noHumidity ? 0 : 12); // humidity with full water storage or 0 humidity
+ te.airQuality = 6; // air quality when sky is seen
+ te.nutrients = 8; // nutrients with full nutrient storage
+
+ int dur = cc.growthDuration(te);
+ int rate = te.calcGrowthRate();
+ if (rate == 0) return; // should not be possible with those stats
+ growthticks = (int) Math.ceil(
+ ((double) dur / (double) rate) * (double) cc.maxSize() * (double) TileEntityCrop.tickRate);
+ if (growthticks < 1) growthticks = 1;
+
+ if (tobeused != null) tobeused.stackSize--;
+
+ this.isValid = true;
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ } finally {
+ if (!cheating) world.setBlock(xyz[0], xyz[1] - 2, xyz[2], GregTech_API.sBlockCasings4, 1, 0);
+ world.setBlockToAir(xyz[0], xyz[1], xyz[2]);
+ }
+ } else {
+ drops = new ArrayList<>();
+ addDrops(world, input.stackSize);
+ }
+ }
+
+ public List<ItemStack> getDrops() {
+ return drops;
+ }
+
+ final Map<String, Double> dropprogress = new HashMap<>();
+ static final Map<String, ItemStack> dropstacks = new HashMap<>();
+
+ public List<ItemStack> getIC2Drops(double timeelapsed) {
+ int r = rn.nextInt(10);
+ if (generations.size() <= r) return new ArrayList<>();
+ double growthPercent = (timeelapsed / (double) growthticks);
+ List<ItemStack> generation = generations.get(r);
+ List<ItemStack> copied = new ArrayList<>();
+ for (ItemStack g : generation) copied.add(g.copy());
+ for (ItemStack s : copied) {
+ double pro = ((double) s.stackSize * growthPercent);
+ s.stackSize = 1;
+ if (dropprogress.containsKey(s.toString()))
+ dropprogress.put(s.toString(), dropprogress.get(s.toString()) + pro);
+ else dropprogress.put(s.toString(), pro);
+ if (!dropstacks.containsKey(s.toString())) dropstacks.put(s.toString(), s.copy());
+ }
+ copied.clear();
+ for (Map.Entry<String, Double> entry : dropprogress.entrySet()) if (entry.getValue() >= 1d) {
+ copied.add(dropstacks.get(entry.getKey()).copy());
+ copied.get(copied.size() - 1).stackSize = entry.getValue().intValue();
+ entry.setValue(entry.getValue() - (double) entry.getValue().intValue());
+ }
+ return copied;
+ }
+
+ public int addDrops(World world, int count) {
+ if (drops == null) drops = new ArrayList<>();
+ if (customDrops != null && customDrops.size() > 0) {
+ @SuppressWarnings("unchecked")
+ ArrayList<ItemStack> d = (ArrayList<ItemStack>) customDrops.clone();
+ for (ItemStack x : drops) {
+ for (Iterator<ItemStack> iterator = d.iterator(); iterator.hasNext();) {
+ ItemStack y = iterator.next();
+ if (GT_Utility.areStacksEqual(x, y)) {
+ x.stackSize += y.stackSize * count;
+ iterator.remove();
+ }
+ }
+ }
+ final int finalCount = count;
+ d.forEach(stack -> {
+ ItemStack i = stack.copy();
+ i.stackSize *= finalCount;
+ drops.add(i);
+ });
+ return 0;
+ } else {
+ if (crop == null) return count;
+ for (int i = 0; i < count; i++) {
+ List<ItemStack> d = crop.getDrops(world, 0, 0, 0, optimalgrowth, 0);
+ for (ItemStack x : drops) for (ItemStack y : d) if (GT_Utility.areStacksEqual(x, y)) {
+ x.stackSize += y.stackSize;
+ y.stackSize = 0;
+ }
+ for (ItemStack x : d) if (x.stackSize > 0) drops.add(x.copy());
+ }
+ }
+ if (!needsreplanting) return 0;
+ for (int i = 0; i < drops.size(); i++) {
+ if (GT_Utility.areStacksEqual(drops.get(i), input)) {
+ int took = Math.min(drops.get(i).stackSize, count);
+ drops.get(i).stackSize -= took;
+ count -= took;
+ if (drops.get(i).stackSize == 0) {
+ drops.remove(i);
+ i--;
+ }
+ if (count == 0) {
+ return 0;
+ }
+ }
+ }
+ if (!findCropRecipe(world)) return count;
+ int totake = count / recipe.getCraftingResult(this).stackSize + 1;
+ for (int i = 0; i < drops.size(); i++) {
+ if (GT_Utility.areStacksEqual(drops.get(i), recipeInput)) {
+ int took = Math.min(drops.get(i).stackSize, totake);
+ drops.get(i).stackSize -= took;
+ totake -= took;
+ if (drops.get(i).stackSize == 0) {
+ drops.remove(i);
+ i--;
+ }
+ if (totake == 0) {
+ return 0;
+ }
+ }
+ }
+ return count;
+ }
+ }
+
+ private static class GreenHouseWorld extends GT_DummyWorld {
+
+ public int x, y, z, meta = 0;
+ public Block block;
+
+ GreenHouseWorld(int x, int y, int z) {
+ super();
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.rand = new GreenHouseRandom();
+ }
+
+ @Override
+ public int getBlockMetadata(int aX, int aY, int aZ) {
+ if (aX == x && aY == y && aZ == z) return 7;
+ return 0;
+ }
+
+ @Override
+ public Block getBlock(int aX, int aY, int aZ) {
+ if (aY == y - 1) return Blocks.farmland;
+ return Blocks.air;
+ }
+
+ @Override
+ public int getBlockLightValue(int p_72957_1_, int p_72957_2_, int p_72957_3_) {
+ return 10;
+ }
+
+ @Override
+ public boolean setBlock(int aX, int aY, int aZ, Block aBlock, int aMeta, int aFlags) {
+ if (aBlock == Blocks.air) return false;
+ if (aX == x && aY == y && aZ == z) return false;
+ block = aBlock;
+ meta = aMeta;
+ return true;
+ }
+ }
+
+ private static class GreenHouseRandom extends Random {
+
+ @Override
+ public int nextInt(int bound) {
+ return 0;
+ }
+ }
+}