aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/core/tileentities
diff options
context:
space:
mode:
authorRaven Szewczyk <git@eigenraven.me>2024-05-24 19:50:35 +0100
committerRaven Szewczyk <git@eigenraven.me>2024-05-24 19:50:35 +0100
commit6d1b2216464d4dad449ac6fcfec476832224a55e (patch)
tree526a0c15f7056313c80e6c0386e025e9b3f61781 /src/main/java/gtPlusPlus/core/tileentities
parentb5d35f40afa606ed1b07061dad82e0521a59c186 (diff)
downloadGT5-Unofficial-6d1b2216464d4dad449ac6fcfec476832224a55e.tar.gz
GT5-Unofficial-6d1b2216464d4dad449ac6fcfec476832224a55e.tar.bz2
GT5-Unofficial-6d1b2216464d4dad449ac6fcfec476832224a55e.zip
Merge addon sources
Diffstat (limited to 'src/main/java/gtPlusPlus/core/tileentities')
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/ModTileEntities.java35
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/base/TileEntityBase.java1419
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/general/TileEntityCircuitProgrammer.java313
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/general/TileEntityDecayablesChest.java378
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/general/TileEntityFishTrap.java294
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/general/TileEntityInfiniteFluid.java148
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/general/TileEntityVolumetricFlaskSetter.java418
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityAdvPooCollector.java140
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityBaseFluidCollector.java241
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPestKiller.java532
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPooCollector.java128
-rw-r--r--src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityProjectTable.java165
12 files changed, 4211 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/core/tileentities/ModTileEntities.java b/src/main/java/gtPlusPlus/core/tileentities/ModTileEntities.java
new file mode 100644
index 0000000000..56cf2fdbab
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/ModTileEntities.java
@@ -0,0 +1,35 @@
+package gtPlusPlus.core.tileentities;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.block.general.BlockSuperLight.TileEntitySuperLight;
+import gtPlusPlus.core.block.machine.Machine_SuperJukebox.TileEntitySuperJukebox;
+import gtPlusPlus.core.tileentities.general.TileEntityCircuitProgrammer;
+import gtPlusPlus.core.tileentities.general.TileEntityDecayablesChest;
+import gtPlusPlus.core.tileentities.general.TileEntityFishTrap;
+import gtPlusPlus.core.tileentities.general.TileEntityInfiniteFluid;
+import gtPlusPlus.core.tileentities.general.TileEntityVolumetricFlaskSetter;
+import gtPlusPlus.core.tileentities.machines.TileEntityAdvPooCollector;
+import gtPlusPlus.core.tileentities.machines.TileEntityPestKiller;
+import gtPlusPlus.core.tileentities.machines.TileEntityPooCollector;
+import gtPlusPlus.core.tileentities.machines.TileEntityProjectTable;
+
+public class ModTileEntities {
+
+ public static void init() {
+ Logger.INFO("Registering Tile Entities.");
+ GameRegistry.registerTileEntity(TileEntityPooCollector.class, "TileEntityPooCollector");
+ GameRegistry.registerTileEntity(TileEntityAdvPooCollector.class, "TileEntityAdvPooCollector");
+ GameRegistry.registerTileEntity(TileEntityFishTrap.class, "TileFishTrap");
+ GameRegistry.registerTileEntity(TileEntityInfiniteFluid.class, "TileInfiniteFluid");
+ GameRegistry.registerTileEntity(TileEntityProjectTable.class, "TileProjectTable");
+ GameRegistry.registerTileEntity(TileEntityCircuitProgrammer.class, "TileCircuitProgrammer");
+ GameRegistry.registerTileEntity(TileEntityDecayablesChest.class, "TileDecayablesChest");
+ GameRegistry.registerTileEntity(TileEntitySuperJukebox.class, "TileEntitySuperJukebox");
+ GameRegistry.registerTileEntity(TileEntitySuperLight.class, "TileEntitySuperLight");
+ GameRegistry.registerTileEntity(TileEntityPestKiller.class, "TileEntityPestKiller");
+
+ GameRegistry.registerTileEntity(TileEntityVolumetricFlaskSetter.class, "TileEntityVolumetricFlaskSetter");
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/base/TileEntityBase.java b/src/main/java/gtPlusPlus/core/tileentities/base/TileEntityBase.java
new file mode 100644
index 0000000000..98f1d67439
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/base/TileEntityBase.java
@@ -0,0 +1,1419 @@
+package gtPlusPlus.core.tileentities.base;
+
+import java.util.UUID;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.IDescribable;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.net.GT_Packet_Block_Event;
+import gregtech.api.util.GT_CoverBehavior;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.covers.CoverInfo;
+import gtPlusPlus.api.interfaces.ILazyCoverable;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.minecraft.BTF_Inventory;
+import gtPlusPlus.core.util.minecraft.gregtech.PollutionUtils;
+import ic2.api.Direction;
+
+public class TileEntityBase extends TileEntity implements ILazyCoverable, IGregTechDeviceInformation, IDescribable {
+
+ private String customName;
+ public String mOwnerName = "null";
+ public String mOwnerUUID = "null";
+ private boolean mIsOwnerOP = false;
+
+ public final BTF_Inventory mInventory;
+
+ public TileEntityBase(int aCapacity) {
+ mInventory = new BTF_Inventory(aCapacity, this);
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ nbt.setBoolean("mIsOwnerOP", this.mIsOwnerOP);
+ nbt.setString("mOwnerName", this.mOwnerName);
+ nbt.setString("mOwnerUUID", this.mOwnerUUID);
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+
+ super.readFromNBT(nbt);
+
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+
+ this.mIsOwnerOP = nbt.getBoolean("mIsOwnerOP");
+ this.mOwnerName = nbt.getString("mOwnerName");
+ this.mOwnerUUID = nbt.getString("mOwnerUUID");
+ }
+
+ @Override
+ public void updateEntity() {
+ long aTick = System.currentTimeMillis();
+ this.isDead = false;
+ if (!firstTicked) {
+ onFirstTick();
+ }
+ try {
+ if (this.isServerSide()) {
+ onPreTick(aTick);
+ }
+ } catch (Throwable t) {
+ Logger.ERROR("Tile Entity Encountered an error in it's pre-tick stage.");
+ t.printStackTrace();
+ }
+ try {
+ if (this.isServerSide()) {
+ onTick(aTick);
+ }
+ } catch (Throwable t) {
+ Logger.ERROR("Tile Entity Encountered an error in it's tick stage.");
+ t.printStackTrace();
+ }
+ try {
+ if (this.isServerSide()) {
+ onPostTick(aTick);
+ }
+ } catch (Throwable t) {
+ Logger.ERROR("Tile Entity Encountered an error in it's post-tick stage.");
+ t.printStackTrace();
+ }
+ }
+
+ public boolean onPreTick(long aTick) {
+ return true;
+ }
+
+ public boolean onTick(long aTick) {
+ try {
+ if (this.isServerSide()) {
+ processRecipe();
+ }
+ } catch (Throwable t) {
+ Logger.ERROR("Tile Entity Encountered an error in it's processing of a recipe stage.");
+ t.printStackTrace();
+ }
+ return true;
+ }
+
+ public boolean onPostTick(long aTick) {
+ return true;
+ }
+
+ public boolean processRecipe() {
+ return true;
+ }
+
+ @Override
+ public boolean canUpdate() {
+ return true;
+ }
+
+ public String getOwner() {
+ if (this.mOwnerName == null) {
+ return "null";
+ }
+ return this.mOwnerName;
+ }
+
+ public UUID getOwnerUUID() {
+ return UUID.fromString(this.mOwnerUUID);
+ }
+
+ public boolean isOwnerOP() {
+ return mIsOwnerOP;
+ }
+
+ public void setOwnerInformation(String mName, String mUUID, boolean mOP) {
+ if (isServerSide()) {
+ if (this.mOwnerName == null || this.mOwnerUUID == null
+ || this.mOwnerName.equals("null")
+ || this.mOwnerUUID.equals("null")) {
+ this.mOwnerName = mName;
+ this.mOwnerUUID = mUUID;
+ this.mIsOwnerOP = mOP;
+ }
+ }
+ }
+
+ @Override
+ public boolean isServerSide() {
+ if (this.hasWorldObj()) {
+ if (!this.getWorldObj().isRemote) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean isClientSide() {
+ return this.worldObj.isRemote;
+ }
+
+ public String getCustomName() {
+ return this.customName;
+ }
+
+ public void setCustomName(String customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.customName : "container.tileentity.name";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return this.customName != null && !this.customName.equals("");
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.mInventory.getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(int aIndex) {
+ return this.mInventory.getStackInSlot(aIndex);
+ }
+
+ @Override
+ public ItemStack decrStackSize(int aIndex, int aAmount) {
+ if (canAccessData()) {
+ mInventoryChanged = true;
+ return mInventory.decrStackSize(aIndex, aAmount);
+ }
+ return null;
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(int p_70304_1_) {
+ return this.mInventory.getStackInSlotOnClosing(p_70304_1_);
+ }
+
+ @Override
+ public void setInventorySlotContents(int p_70299_1_, ItemStack p_70299_2_) {
+ this.mInventory.setInventorySlotContents(p_70299_1_, p_70299_2_);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.mInventory.getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(EntityPlayer p_70300_1_) {
+ return this.mInventory.isUseableByPlayer(p_70300_1_);
+ }
+
+ @Override
+ public void openInventory() {
+ this.mInventory.openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ this.mInventory.closeInventory();
+ }
+
+ /**
+ * Can put aStack into Slot
+ */
+ @Override
+ public boolean isItemValidForSlot(int aIndex, ItemStack aStack) {
+ return canAccessData() && mInventory.isItemValidForSlot(aIndex, aStack);
+ }
+
+ /**
+ * returns all valid Inventory Slots, no matter which Side (Unless it's covered). The Side Stuff is done in the
+ * following two Functions.
+ */
+ @Override
+ public int[] getAccessibleSlotsFromSide(int ordinalSide) {
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+ CoverInfo coverInfo = getCoverInfoAtSide(side);
+ if (canAccessData() && (coverInfo.letsItemsOut(-1) || coverInfo.letsItemsIn(-1)))
+ return mInventory.getAccessibleSlotsFromSide(ordinalSide);
+ return new int[0];
+ }
+
+ /**
+ * Can put aStack into Slot at Side
+ */
+ @Override
+ public boolean canInsertItem(int aIndex, ItemStack aStack, int ordinalSide) {
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+ return canAccessData() && (mRunningThroughTick || !mInputDisabled)
+ && getCoverInfoAtSide(side).letsItemsIn(aIndex)
+ && mInventory.canInsertItem(aIndex, aStack, ordinalSide);
+ }
+
+ /**
+ * Can pull aStack out of Slot from Side
+ */
+ @Override
+ public boolean canExtractItem(int aIndex, ItemStack aStack, int ordinalSide) {
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+ return canAccessData() && (mRunningThroughTick || !mOutputDisabled)
+ && getCoverInfoAtSide(side).letsItemsOut(aIndex)
+ && mInventory.canExtractItem(aIndex, aStack, ordinalSide);
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return this.canAccessData() ? this.mInventory.isValidSlot(aIndex) : false;
+ }
+
+ private final GT_CoverBehavior[] mCoverBehaviors = new GT_CoverBehavior[] { GregTech_API.sNoBehavior,
+ GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior,
+ GregTech_API.sNoBehavior };
+ protected TileEntityBase mMetaTileEntity;
+ protected long mStoredEnergy = 0;
+ protected int mAverageEUInputIndex = 0, mAverageEUOutputIndex = 0;
+ protected boolean mReleaseEnergy = false;
+ protected int[] mAverageEUInput = new int[11], mAverageEUOutput = new int[11];
+ private boolean[] mActiveEUInputs = new boolean[] { false, false, false, false, false, false },
+ mActiveEUOutputs = new boolean[] { false, false, false, false, false, false };
+ private byte[] mSidedRedstone = new byte[] { 15, 15, 15, 15, 15, 15 };
+ private int[] mCoverSides = new int[] { 0, 0, 0, 0, 0, 0 }, mCoverData = new int[] { 0, 0, 0, 0, 0, 0 },
+ mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING];
+ private boolean mHasEnoughEnergy = true;
+ protected boolean mRunningThroughTick = false;
+ protected boolean mInputDisabled = false;
+ protected boolean mOutputDisabled = false;
+ private boolean mMuffler = false;
+ private boolean mLockUpgrade = false;
+ private boolean mActive = false;
+ private boolean mRedstone = false;
+ private boolean mWorkUpdate = false;
+ private boolean mSteamConverter = false;
+ private boolean mInventoryChanged = false;
+ private boolean mWorks = true;
+ private boolean mNeedsUpdate = true;
+ private boolean mNeedsBlockUpdate = true;
+ private boolean mSendClientData = false;
+ private boolean oRedstone = false;
+ private boolean mEnergyStateReady = false;
+ private byte mColor = 0, oColor = 0, mStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0,
+ oTexturePage = 0, oLightValueClient = -1, oLightValue = -1, mLightValue = 0, mOtherUpgrades = 0, mFacing = 0,
+ oFacing = 0, mWorkData = 0;
+ private int mDisplayErrorCode = 0, oX = 0, oY = 0, oZ = 0, mTimeStatisticsIndex = 0, mLagWarningCount = 0;
+ private short mID = 0;
+ protected long mTickTimer = 0;
+ private long oOutput = 0;
+ private long mAcceptedAmperes = Long.MAX_VALUE;
+
+ /**
+ * Cover Support
+ */
+ public void issueClientUpdate() {
+ this.mSendClientData = true;
+ }
+
+ protected final boolean canAccessData() {
+ return !isDead() && !this.isInvalid();
+ }
+
+ @Override
+ public void issueBlockUpdate() {
+ super.markDirty();
+ }
+
+ @Override
+ public void issueCoverUpdate(ForgeDirection side) {
+ this.issueClientUpdate();
+ }
+
+ @Override
+ public void receiveCoverData(ForgeDirection coverSide, int coverID, int coverData) {
+ if (coverSide != ForgeDirection.UNKNOWN && (mCoverSides[coverSide.ordinal()] == coverID))
+ setCoverDataAtSide(coverSide, coverData);
+ }
+
+ @Override
+ public long getTimer() {
+ return this.mTickTimer;
+ }
+
+ @Override
+ public long getOutputAmperage() {
+ return this.canAccessData() && this.mMetaTileEntity.isElectric() ? this.mMetaTileEntity.maxAmperesOut() : 0L;
+ }
+
+ @Override
+ public long getOutputVoltage() {
+ return this.canAccessData() && this.mMetaTileEntity.isElectric() && this.mMetaTileEntity.isEnetOutput()
+ ? this.mMetaTileEntity.maxEUOutput()
+ : 0L;
+ }
+
+ @Override
+ public long getInputAmperage() {
+ return this.canAccessData() && this.mMetaTileEntity.isElectric() ? this.mMetaTileEntity.maxAmperesIn() : 0L;
+ }
+
+ @Override
+ public long getInputVoltage() {
+ return this.canAccessData() && this.mMetaTileEntity.isElectric() ? this.mMetaTileEntity.maxEUInput()
+ : 2147483647L;
+ }
+
+ @Override
+ public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLessEnergy) {
+ return !this.canAccessData() ? false
+ : (this.mHasEnoughEnergy = this.decreaseStoredEU(aEnergy, aIgnoreTooLessEnergy));
+ }
+
+ @Override
+ public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) {
+ if (!this.canAccessData()) {
+ return false;
+ } else if (this.getStoredEU() >= this.getEUCapacity() && !aIgnoreTooMuchEnergy) {
+ return false;
+ } else {
+ this.setStoredEU(this.mMetaTileEntity.getEUVar() + aEnergy);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean inputEnergyFrom(ForgeDirection side) {
+ return side == ForgeDirection.UNKNOWN ? true
+ : (!this.isServerSide() ? this.isEnergyInputSide(side)
+ : side != ForgeDirection.UNKNOWN && this.mActiveEUInputs[side.ordinal()] && !this.mReleaseEnergy);
+ }
+
+ @Override
+ public boolean outputsEnergyTo(ForgeDirection side) {
+ return side == ForgeDirection.UNKNOWN ? true
+ : (!this.isServerSide() ? this.isEnergyOutputSide(side)
+ : side != ForgeDirection.UNKNOWN && this.mActiveEUOutputs[side.ordinal()] || this.mReleaseEnergy);
+ }
+
+ private boolean isEnergyInputSide(ForgeDirection side) {
+ if (side != ForgeDirection.UNKNOWN) {
+ if (!this.getCoverInfoAtSide(side)
+ .letsEnergyIn()) {
+ return false;
+ }
+
+ if (this.isInvalid() || this.mReleaseEnergy) {
+ return false;
+ }
+
+ if (this.canAccessData() && this.mMetaTileEntity.isElectric() && this.mMetaTileEntity.isEnetInput()) {
+ return this.mMetaTileEntity.isInputFacing(side);
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isEnergyOutputSide(ForgeDirection side) {
+ if (side != ForgeDirection.UNKNOWN) {
+ if (!this.getCoverInfoAtSide(side)
+ .letsEnergyOut()) {
+ return false;
+ }
+
+ if (this.isInvalid() || this.mReleaseEnergy) {
+ return this.mReleaseEnergy;
+ }
+
+ if (this.canAccessData() && this.mMetaTileEntity.isElectric() && this.mMetaTileEntity.isEnetOutput()) {
+ return this.mMetaTileEntity.isOutputFacing(side);
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isOutputFacing(ForgeDirection side) {
+ return false;
+ }
+
+ public boolean isInputFacing(ForgeDirection side) {
+ return false;
+ }
+
+ private final TileEntity[] mBufferedTileEntities = new TileEntity[6];
+ public boolean ignoreUnloadedChunks = true;
+ public boolean isDead = false;
+
+ private void clearNullMarkersFromTileEntityBuffer() {
+ for (int i = 0; i < this.mBufferedTileEntities.length; ++i) {
+ if (this.mBufferedTileEntities[i] == this) {
+ this.mBufferedTileEntities[i] = null;
+ }
+ }
+ }
+
+ protected final void clearTileEntityBuffer() {
+ for (int i = 0; i < this.mBufferedTileEntities.length; ++i) {
+ this.mBufferedTileEntities[i] = null;
+ }
+ }
+
+ @Override
+ public final World getWorld() {
+ return this.worldObj;
+ }
+
+ @Override
+ public final int getXCoord() {
+ return this.xCoord;
+ }
+
+ @Override
+ public final short getYCoord() {
+ return (short) this.yCoord;
+ }
+
+ @Override
+ public final int getZCoord() {
+ return this.zCoord;
+ }
+
+ @Override
+ public final int getOffsetX(ForgeDirection side, int aMultiplier) {
+ return this.xCoord + side.offsetX * aMultiplier;
+ }
+
+ @Override
+ public final short getOffsetY(ForgeDirection side, int aMultiplier) {
+ return (short) (this.yCoord + side.offsetY * aMultiplier);
+ }
+
+ @Override
+ public final int getOffsetZ(ForgeDirection side, int aMultiplier) {
+ return this.zCoord + side.offsetZ * aMultiplier;
+ }
+
+ @Override
+ public final int getRandomNumber(int aRange) {
+ return this.worldObj.rand.nextInt(aRange);
+ }
+
+ @Override
+ public final BiomeGenBase getBiome(int aX, int aZ) {
+ return this.worldObj.getBiomeGenForCoords(aX, aZ);
+ }
+
+ @Override
+ public final BiomeGenBase getBiome() {
+ return this.getBiome(this.xCoord, this.zCoord);
+ }
+
+ @Override
+ public final Block getBlockOffset(int aX, int aY, int aZ) {
+ return this.getBlock(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final Block getBlockAtSide(ForgeDirection side) {
+ return this.getBlockAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final Block getBlockAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getBlock(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final byte getMetaIDOffset(int aX, int aY, int aZ) {
+ return this.getMetaID(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final byte getMetaIDAtSide(ForgeDirection side) {
+ return this.getMetaIDAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final byte getMetaIDAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getMetaID(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final byte getLightLevelOffset(int aX, int aY, int aZ) {
+ return this.getLightLevel(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final byte getLightLevelAtSide(ForgeDirection side) {
+ return this.getLightLevelAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final byte getLightLevelAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getLightLevel(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final boolean getOpacityOffset(int aX, int aY, int aZ) {
+ return this.getOpacity(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final boolean getOpacityAtSide(ForgeDirection side) {
+ return this.getOpacityAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final boolean getOpacityAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getOpacity(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final boolean getSkyOffset(int aX, int aY, int aZ) {
+ return this.getSky(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final boolean getSkyAtSide(ForgeDirection side) {
+ return this.getSkyAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final boolean getSkyAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getSky(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final boolean getAirOffset(int aX, int aY, int aZ) {
+ return this.getAir(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final boolean getAirAtSide(ForgeDirection side) {
+ return this.getAirAtSideAndDistance(side, 1);
+ }
+
+ @Override
+ public final boolean getAirAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return this.getAir(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final TileEntity getTileEntityOffset(int aX, int aY, int aZ) {
+ return this.getTileEntity(this.xCoord + aX, this.yCoord + aY, this.zCoord + aZ);
+ }
+
+ @Override
+ public final TileEntity getTileEntityAtSideAndDistance(ForgeDirection side, int aDistance) {
+ return aDistance == 1 ? this.getTileEntityAtSide(side)
+ : this.getTileEntity(
+ this.getOffsetX(side, aDistance),
+ this.getOffsetY(side, aDistance),
+ this.getOffsetZ(side, aDistance));
+ }
+
+ @Override
+ public final IInventory getIInventory(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntity(aX, aY, aZ);
+ return tTileEntity instanceof IInventory ? (IInventory) tTileEntity : null;
+ }
+
+ @Override
+ public final IInventory getIInventoryOffset(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntityOffset(aX, aY, aZ);
+ return tTileEntity instanceof IInventory ? (IInventory) tTileEntity : null;
+ }
+
+ @Override
+ public final IInventory getIInventoryAtSide(ForgeDirection side) {
+ TileEntity tTileEntity = this.getTileEntityAtSide(side);
+ return tTileEntity instanceof IInventory ? (IInventory) tTileEntity : null;
+ }
+
+ @Override
+ public final IInventory getIInventoryAtSideAndDistance(ForgeDirection side, int aDistance) {
+ TileEntity tTileEntity = this.getTileEntityAtSideAndDistance(side, aDistance);
+ return tTileEntity instanceof IInventory ? (IInventory) tTileEntity : null;
+ }
+
+ @Override
+ public final IFluidHandler getITankContainer(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntity(aX, aY, aZ);
+ return tTileEntity instanceof IFluidHandler ? (IFluidHandler) tTileEntity : null;
+ }
+
+ @Override
+ public final IFluidHandler getITankContainerOffset(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntityOffset(aX, aY, aZ);
+ return tTileEntity instanceof IFluidHandler ? (IFluidHandler) tTileEntity : null;
+ }
+
+ @Override
+ public final IFluidHandler getITankContainerAtSide(ForgeDirection side) {
+ TileEntity tTileEntity = this.getTileEntityAtSide(side);
+ return tTileEntity instanceof IFluidHandler ? (IFluidHandler) tTileEntity : null;
+ }
+
+ @Override
+ public final IFluidHandler getITankContainerAtSideAndDistance(ForgeDirection side, int aDistance) {
+ TileEntity tTileEntity = this.getTileEntityAtSideAndDistance(side, aDistance);
+ return tTileEntity instanceof IFluidHandler ? (IFluidHandler) tTileEntity : null;
+ }
+
+ @Override
+ public final IGregTechTileEntity getIGregTechTileEntity(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntity(aX, aY, aZ);
+ return tTileEntity instanceof IGregTechTileEntity ? (IGregTechTileEntity) tTileEntity : null;
+ }
+
+ @Override
+ public final IGregTechTileEntity getIGregTechTileEntityOffset(int aX, int aY, int aZ) {
+ TileEntity tTileEntity = this.getTileEntityOffset(aX, aY, aZ);
+ return tTileEntity instanceof IGregTechTileEntity ? (IGregTechTileEntity) tTileEntity : null;
+ }
+
+ @Override
+ public final IGregTechTileEntity getIGregTechTileEntityAtSide(ForgeDirection side) {
+ TileEntity tTileEntity = this.getTileEntityAtSide(side);
+ return tTileEntity instanceof IGregTechTileEntity ? (IGregTechTileEntity) tTileEntity : null;
+ }
+
+ @Override
+ public final IGregTechTileEntity getIGregTechTileEntityAtSideAndDistance(ForgeDirection side, int aDistance) {
+ TileEntity tTileEntity = this.getTileEntityAtSideAndDistance(side, aDistance);
+ return tTileEntity instanceof IGregTechTileEntity ? (IGregTechTileEntity) tTileEntity : null;
+ }
+
+ @Override
+ public final Block getBlock(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? Blocks.air
+ : this.worldObj.getBlock(aX, aY, aZ);
+ }
+
+ @Override
+ public final byte getMetaID(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? 0
+ : (byte) this.worldObj.getBlockMetadata(aX, aY, aZ);
+ }
+
+ @Override
+ public final byte getLightLevel(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? 0
+ : (byte) ((int) (this.worldObj.getLightBrightness(aX, aY, aZ) * 15.0F));
+ }
+
+ @Override
+ public final boolean getSky(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? true
+ : this.worldObj.canBlockSeeTheSky(aX, aY, aZ);
+ }
+
+ @Override
+ public final boolean getOpacity(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? false
+ : GT_Utility.isOpaqueBlock(this.worldObj, aX, aY, aZ);
+ }
+
+ @Override
+ public final boolean getAir(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? true
+ : GT_Utility.isBlockAir(this.worldObj, aX, aY, aZ);
+ }
+
+ @Override
+ public final TileEntity getTileEntity(int aX, int aY, int aZ) {
+ return this.ignoreUnloadedChunks && this.crossedChunkBorder(aX, aZ) && !this.worldObj.blockExists(aX, aY, aZ)
+ ? null
+ : this.worldObj.getTileEntity(aX, aY, aZ);
+ }
+
+ @Override
+ public final TileEntity getTileEntityAtSide(ForgeDirection side) {
+ final int ordinalSide = side.ordinal();
+ if (side != ForgeDirection.UNKNOWN && this.mBufferedTileEntities[ordinalSide] != this) {
+ int tX = this.getOffsetX(side, 1);
+ short tY = this.getOffsetY(side, 1);
+ int tZ = this.getOffsetZ(side, 1);
+ if (this.crossedChunkBorder(tX, tZ)) {
+ this.mBufferedTileEntities[ordinalSide] = null;
+ if (this.ignoreUnloadedChunks && !this.worldObj.blockExists(tX, tY, tZ)) {
+ return null;
+ }
+ }
+
+ if (this.mBufferedTileEntities[ordinalSide] == null) {
+ this.mBufferedTileEntities[ordinalSide] = this.worldObj.getTileEntity(tX, tY, tZ);
+ if (this.mBufferedTileEntities[ordinalSide] == null) {
+ this.mBufferedTileEntities[ordinalSide] = this;
+ return null;
+ } else {
+ return this.mBufferedTileEntities[ordinalSide];
+ }
+ } else if (this.mBufferedTileEntities[ordinalSide].isInvalid()) {
+ this.mBufferedTileEntities[ordinalSide] = null;
+ return this.getTileEntityAtSide(side);
+ } else {
+ return this.mBufferedTileEntities[ordinalSide].xCoord == tX
+ && this.mBufferedTileEntities[ordinalSide].yCoord == tY
+ && this.mBufferedTileEntities[ordinalSide].zCoord == tZ ? this.mBufferedTileEntities[ordinalSide]
+ : null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isDead() {
+ return this.isDead || this.isInvalidTileEntity();
+ }
+
+ @Override
+ public void validate() {
+ this.clearNullMarkersFromTileEntityBuffer();
+ super.validate();
+ }
+
+ @Override
+ public void invalidate() {
+ this.clearNullMarkersFromTileEntityBuffer();
+ super.invalidate();
+ }
+
+ @Override
+ public void onChunkUnload() {
+ this.clearNullMarkersFromTileEntityBuffer();
+ super.onChunkUnload();
+ this.isDead = true;
+ }
+
+ public final void onAdjacentBlockChange(int aX, int aY, int aZ) {
+ this.clearNullMarkersFromTileEntityBuffer();
+ }
+
+ @Override
+ public final void sendBlockEvent(byte aID, byte aValue) {
+ GT_Values.NW.sendPacketToAllPlayersInRange(
+ this.worldObj,
+ new GT_Packet_Block_Event(this.xCoord, (short) this.yCoord, this.zCoord, aID, aValue),
+ this.xCoord,
+ this.zCoord);
+ }
+
+ private boolean crossedChunkBorder(int aX, int aZ) {
+ return aX >> 4 != this.xCoord >> 4 || aZ >> 4 != this.zCoord >> 4;
+ }
+
+ public final void setOnFire() {
+ GT_Utility.setCoordsOnFire(this.worldObj, this.xCoord, this.yCoord, this.zCoord, false);
+ }
+
+ public final void setToFire() {
+ this.worldObj.setBlock(this.xCoord, this.yCoord, this.zCoord, Blocks.fire);
+ }
+
+ @Override
+ public byte getInternalInputRedstoneSignal(ForgeDirection side) {
+ return (byte) (getCoverBehaviorAtSide(side).getRedstoneInput(
+ side,
+ getInputRedstoneSignal(side),
+ getCoverIDAtSide(side),
+ getCoverDataAtSide(side),
+ this) & 15);
+ }
+
+ @Override
+ public byte getInputRedstoneSignal(ForgeDirection side) {
+ return (byte) (worldObj
+ .getIndirectPowerLevelTo(getOffsetX(side, 1), getOffsetY(side, 1), getOffsetZ(side, 1), side.ordinal())
+ & 15);
+ }
+
+ @Override
+ public byte getOutputRedstoneSignal(ForgeDirection side) {
+ return getCoverBehaviorAtSide(side)
+ .manipulatesSidedRedstoneOutput(side, getCoverIDAtSide(side), getCoverDataAtSide(side), this)
+ ? mSidedRedstone[side.ordinal()]
+ : getGeneralRS(side);
+ }
+
+ public boolean allowGeneralRedstoneOutput() {
+ return false;
+ }
+
+ @Override
+ public byte getGeneralRS(ForgeDirection side) {
+ return allowGeneralRedstoneOutput() ? mSidedRedstone[side.ordinal()] : 0;
+ }
+
+ @Override
+ public void setInternalOutputRedstoneSignal(ForgeDirection side, byte aStrength) {
+ if (!getCoverBehaviorAtSide(side)
+ .manipulatesSidedRedstoneOutput(side, getCoverIDAtSide(side), getCoverDataAtSide(side), this))
+ setOutputRedstoneSignal(side, aStrength);
+ }
+
+ @Override
+ public void setOutputRedstoneSignal(ForgeDirection side, byte aStrength) {
+ aStrength = (byte) Math.min(Math.max(0, aStrength), 15);
+ if (side != ForgeDirection.UNKNOWN && mSidedRedstone[side.ordinal()] != aStrength) {
+ mSidedRedstone[side.ordinal()] = aStrength;
+ issueBlockUpdate();
+ }
+ }
+
+ @Override
+ public boolean hasInventoryBeenModified() {
+ return mInventoryChanged;
+ }
+
+ @Override
+ public void setGenericRedstoneOutput(boolean aOnOff) {
+ mRedstone = aOnOff;
+ }
+
+ @Override
+ public GT_CoverBehavior getCoverBehaviorAtSide(ForgeDirection side) {
+ return side != ForgeDirection.UNKNOWN ? mCoverBehaviors[side.ordinal()] : GregTech_API.sNoBehavior;
+ }
+
+ @Override
+ public void setCoverIDAtSide(ForgeDirection side, int aID) {
+ if (setCoverIDAtSideNoUpdate(side, aID)) {
+ issueCoverUpdate(side);
+ issueBlockUpdate();
+ }
+ }
+
+ @Override
+ public boolean setCoverIDAtSideNoUpdate(ForgeDirection side, int aID) {
+ if (side != ForgeDirection.UNKNOWN) {
+ final int ordinalSide = side.ordinal();
+ mCoverSides[ordinalSide] = aID;
+ mCoverData[ordinalSide] = 0;
+ mCoverBehaviors[ordinalSide] = (GT_CoverBehavior) GregTech_API.getCoverBehaviorNew(aID);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void setCoverIdAndDataAtSide(ForgeDirection side, int aId, ISerializableObject aData) {
+ setCoverIDAtSide(side, aId);
+ setCoverDataAtSide(side, aData);
+ }
+
+ @Override
+ public void setCoverItemAtSide(ForgeDirection side, ItemStack aCover) {
+ GregTech_API.getCoverBehaviorNew(aCover)
+ .placeCover(side, aCover, this);
+ }
+
+ @Override
+ public int getCoverIDAtSide(ForgeDirection side) {
+ if (side != ForgeDirection.UNKNOWN) return mCoverSides[side.ordinal()];
+ return 0;
+ }
+
+ @Override
+ public ItemStack getCoverItemAtSide(ForgeDirection side) {
+ return GT_Utility.intToStack(getCoverIDAtSide(side));
+ }
+
+ @Override
+ public boolean canPlaceCoverIDAtSide(ForgeDirection side, int aID) {
+ return getCoverIDAtSide(side) == 0;
+ }
+
+ @Override
+ public boolean canPlaceCoverItemAtSide(ForgeDirection side, ItemStack aCover) {
+ return getCoverIDAtSide(side) == 0;
+ }
+
+ @Override
+ public void setCoverDataAtSide(ForgeDirection side, int aData) {
+ if (side != ForgeDirection.UNKNOWN) mCoverData[side.ordinal()] = aData;
+ }
+
+ @Override
+ public int getCoverDataAtSide(ForgeDirection side) {
+ if (side != ForgeDirection.UNKNOWN) return mCoverData[side.ordinal()];
+ return 0;
+ }
+
+ public byte getLightValue() {
+ return mLightValue;
+ }
+
+ @Override
+ public void setLightValue(byte aLightValue) {
+ mLightValue = (byte) (aLightValue & 15);
+ }
+
+ @Override
+ public long getAverageElectricInput() {
+ int rEU = 0;
+ for (int i = 0; i < mAverageEUInput.length; i++) {
+ if (i != mAverageEUInputIndex) rEU += mAverageEUInput[i];
+ }
+ return rEU / (mAverageEUInput.length - 1);
+ }
+
+ @Override
+ public long getAverageElectricOutput() {
+ int rEU = 0;
+ for (int i = 0; i < mAverageEUOutput.length; i++) {
+ if (i != mAverageEUOutputIndex) rEU += mAverageEUOutput[i];
+ }
+ return rEU / (mAverageEUOutput.length - 1);
+ }
+
+ public boolean hasSidedRedstoneOutputBehavior() {
+ return false;
+ }
+
+ @Override
+ public boolean dropCover(ForgeDirection side, ForgeDirection droppedSide, boolean aForced) {
+ if (getCoverBehaviorAtSide(side)
+ .onCoverRemoval(side, getCoverIDAtSide(side), mCoverData[side.ordinal()], this, aForced) || aForced) {
+ ItemStack tStack = getCoverBehaviorAtSide(side)
+ .getDrop(side, getCoverIDAtSide(side), getCoverDataAtSide(side), this);
+ if (tStack != null) {
+ tStack.setTagCompound(null);
+ EntityItem tEntity = new EntityItem(
+ worldObj,
+ getOffsetX(droppedSide, 1) + 0.5,
+ getOffsetY(droppedSide, 1) + 0.5,
+ getOffsetZ(droppedSide, 1) + 0.5,
+ tStack);
+ tEntity.motionX = 0;
+ tEntity.motionY = 0;
+ tEntity.motionZ = 0;
+ worldObj.spawnEntityInWorld(tEntity);
+ }
+ setCoverIDAtSide(side, 0);
+ if (mMetaTileEntity.hasSidedRedstoneOutputBehavior()) {
+ setOutputRedstoneSignal(side, (byte) 0);
+ } else {
+ setOutputRedstoneSignal(side, (byte) 15);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public String getOwnerName() {
+ if (GT_Utility.isStringInvalid(mOwnerName)) return "Player";
+ return mOwnerName;
+ }
+
+ public String setOwnerName(String aName) {
+ if (GT_Utility.isStringInvalid(aName)) return mOwnerName = "Player";
+ return mOwnerName = aName;
+ }
+
+ @Override
+ public byte getComparatorValue(ForgeDirection side) {
+ return canAccessData() ? mMetaTileEntity.getComparatorValue(side) : 0;
+ }
+
+ @Override
+ public byte getStrongOutputRedstoneSignal(ForgeDirection side) {
+ final int ordinalSide = side.ordinal();
+ return side != ForgeDirection.UNKNOWN && (mStrongRedstone & (1 << ordinalSide)) != 0
+ ? (byte) (mSidedRedstone[ordinalSide] & 15)
+ : 0;
+ }
+
+ @Override
+ public void setStrongOutputRedstoneSignal(ForgeDirection side, byte aStrength) {
+ mStrongRedstone |= (1 << side.ordinal());
+ setOutputRedstoneSignal(side, aStrength);
+ }
+
+ @Override
+ public long injectEnergyUnits(ForgeDirection side, long aVoltage, long aAmperage) {
+ if (!canAccessData() || !mMetaTileEntity.isElectric()
+ || !inputEnergyFrom(side)
+ || aAmperage <= 0
+ || aVoltage <= 0
+ || getStoredEU() >= getEUCapacity()
+ || mMetaTileEntity.maxAmperesIn() <= mAcceptedAmperes) return 0;
+ if (aVoltage > getInputVoltage()) {
+ doExplosion(aVoltage);
+ return 0;
+ }
+ if (increaseStoredEnergyUnits(
+ aVoltage * (aAmperage = Math.min(
+ aAmperage,
+ Math.min(
+ mMetaTileEntity.maxAmperesIn() - mAcceptedAmperes,
+ 1 + ((getEUCapacity() - getStoredEU()) / aVoltage)))),
+ true)) {
+ mAverageEUInput[mAverageEUInputIndex] += aVoltage * aAmperage;
+ mAcceptedAmperes += aAmperage;
+ return aAmperage;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean drainEnergyUnits(ForgeDirection side, long aVoltage, long aAmperage) {
+ if (!canAccessData() || !mMetaTileEntity.isElectric()
+ || !outputsEnergyTo(side)
+ || getStoredEU() - (aVoltage * aAmperage) < mMetaTileEntity.getMinimumStoredEU()) return false;
+ if (decreaseStoredEU(aVoltage * aAmperage, false)) {
+ mAverageEUOutput[mAverageEUOutputIndex] += aVoltage * aAmperage;
+ return true;
+ }
+ return false;
+ }
+
+ public double getOutputEnergyUnitsPerTick() {
+ return oOutput;
+ }
+
+ public boolean isTeleporterCompatible(ForgeDirection side) {
+ return false;
+ }
+
+ public double demandedEnergyUnits() {
+ if (mReleaseEnergy || !canAccessData() || !mMetaTileEntity.isEnetInput()) return 0;
+ return getEUCapacity() - getStoredEU();
+ }
+
+ public double injectEnergyUnits(ForgeDirection aDirection, double aAmount) {
+ return injectEnergyUnits(aDirection, (int) aAmount, 1) > 0 ? 0 : aAmount;
+ }
+
+ public boolean acceptsEnergyFrom(TileEntity aEmitter, ForgeDirection aDirection) {
+ return inputEnergyFrom(aDirection);
+ }
+
+ public boolean emitsEnergyTo(TileEntity aReceiver, ForgeDirection aDirection) {
+ return outputsEnergyTo(aDirection);
+ }
+
+ public double getOfferedEnergy() {
+ return (canAccessData() && getStoredEU() - mMetaTileEntity.getMinimumStoredEU() >= oOutput)
+ ? Math.max(0, oOutput)
+ : 0;
+ }
+
+ public void drawEnergy(double amount) {
+ mAverageEUOutput[mAverageEUOutputIndex] += amount;
+ decreaseStoredEU((int) amount, true);
+ }
+
+ public int injectEnergy(ForgeDirection aForgeDirection, int aAmount) {
+ return injectEnergyUnits(aForgeDirection, aAmount, 1) > 0 ? 0 : aAmount;
+ }
+
+ public int addEnergy(int aEnergy) {
+ if (!canAccessData()) return 0;
+ if (aEnergy > 0) increaseStoredEnergyUnits(aEnergy, true);
+ else decreaseStoredEU(-aEnergy, true);
+ return (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getEUVar());
+ }
+
+ public boolean isAddedToEnergyNet() {
+ return false;
+ }
+
+ public int demandsEnergy() {
+ if (mReleaseEnergy || !canAccessData() || !mMetaTileEntity.isEnetInput()) return 0;
+ return getCapacity() - getStored();
+ }
+
+ public int getCapacity() {
+ return (int) Math.min(Integer.MAX_VALUE, getEUCapacity());
+ }
+
+ public int getStored() {
+ return (int) Math.min(Integer.MAX_VALUE, Math.min(getStoredEU(), getCapacity()));
+ }
+
+ public void setStored(int aEU) {
+ if (canAccessData()) setStoredEU(aEU);
+ }
+
+ public int getMaxSafeInput() {
+ return (int) Math.min(Integer.MAX_VALUE, getInputVoltage());
+ }
+
+ public int getMaxEnergyOutput() {
+ if (mReleaseEnergy) return Integer.MAX_VALUE;
+ return getOutput();
+ }
+
+ public int getOutput() {
+ return (int) Math.min(Integer.MAX_VALUE, oOutput);
+ }
+
+ public int injectEnergy(Direction aDirection, int aAmount) {
+ return injectEnergyUnits(aDirection.toForgeDirection(), aAmount, 1) > 0 ? 0 : aAmount;
+ }
+
+ public boolean acceptsEnergyFrom(TileEntity aReceiver, Direction aDirection) {
+ return inputEnergyFrom(aDirection.toForgeDirection());
+ }
+
+ public boolean emitsEnergyTo(TileEntity aReceiver, Direction aDirection) {
+ return outputsEnergyTo(aDirection.toForgeDirection());
+ }
+
+ @Override
+ public boolean isInvalidTileEntity() {
+ return isInvalid();
+ }
+
+ @Override
+ public boolean addStackToSlot(int aIndex, ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) return true;
+ if (aIndex < 0 || aIndex >= getSizeInventory()) return false;
+ ItemStack tStack = getStackInSlot(aIndex);
+ if (GT_Utility.isStackInvalid(tStack)) {
+ setInventorySlotContents(aIndex, aStack);
+ return true;
+ }
+ aStack = GT_OreDictUnificator.get(aStack);
+ if (GT_Utility.areStacksEqual(tStack, aStack)
+ && tStack.stackSize + aStack.stackSize <= Math.min(aStack.getMaxStackSize(), getInventoryStackLimit())) {
+ tStack.stackSize += aStack.stackSize;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) {
+ return addStackToSlot(aIndex, GT_Utility.copyAmount(aAmount, aStack));
+ }
+
+ @Override
+ public void markDirty() {
+ super.markDirty();
+ mInventoryChanged = true;
+ }
+
+ /**
+ * To Do
+ */
+ public boolean isElectric() {
+ return true;
+ }
+
+ public boolean isEnetOutput() {
+ return false;
+ }
+
+ public boolean isEnetInput() {
+ return false;
+ }
+
+ public long maxEUStore() {
+ return 0L;
+ }
+
+ public long maxEUInput() {
+ return 0L;
+ }
+
+ public long maxEUOutput() {
+ return 0L;
+ }
+
+ public long maxAmperesOut() {
+ return 1L;
+ }
+
+ public long maxAmperesIn() {
+ return 1L;
+ }
+
+ public void doEnergyExplosion() {
+ if (this.getUniversalEnergyCapacity() > 0L
+ && this.getUniversalEnergyStored() >= this.getUniversalEnergyCapacity() / 5L) {
+ this.doExplosion(
+ this.oOutput * (long) (this.getUniversalEnergyStored() >= this.getUniversalEnergyCapacity() ? 4
+ : (this.getUniversalEnergyStored() >= this.getUniversalEnergyCapacity() / 2L ? 2 : 1)));
+ GT_Mod arg9999 = GT_Mod.instance;
+ GT_Mod.achievements.issueAchievement(
+ this.getWorldObj()
+ .getPlayerEntityByName(this.mOwnerName),
+ "electricproblems");
+ }
+ }
+
+ public void doExplosion(long aAmount) {
+ if (this.canAccessData()) {
+ if (GregTech_API.sMachineWireFire && this.mMetaTileEntity.isElectric()) {
+ try {
+ this.mReleaseEnergy = true;
+ Util.emitEnergyToNetwork(GT_Values.V[5], Math.max(1L, this.getStoredEU() / GT_Values.V[5]), this);
+ } catch (Exception arg4) {}
+ }
+ this.mReleaseEnergy = false;
+ this.onExplosion();
+ PollutionUtils.addPollution(this, 100000);
+ this.mMetaTileEntity.doExplosion(aAmount);
+ }
+ }
+
+ public void onExplosion() {}
+
+ @Override
+ public String[] getDescription() {
+ return this.canAccessData() ? this.mMetaTileEntity.getDescription() : new String[0];
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return null;
+ }
+
+ public long getEUVar() {
+ return this.mStoredEnergy;
+ }
+
+ public void setEUVar(long aEnergy) {
+ this.mStoredEnergy = aEnergy;
+ }
+
+ @Override
+ public long getStoredEU() {
+ return this.canAccessData() ? Math.min(this.mMetaTileEntity.getEUVar(), this.getEUCapacity()) : 0L;
+ }
+
+ @Override
+ public long getEUCapacity() {
+ return this.canAccessData() ? this.mMetaTileEntity.maxEUStore() : 0L;
+ }
+
+ public long getMinimumStoredEU() {
+ return 512L;
+ }
+
+ public boolean setStoredEU(long aEnergy) {
+ if (!this.canAccessData()) {
+ return false;
+ } else {
+ if (aEnergy < 0L) {
+ aEnergy = 0L;
+ }
+
+ this.mMetaTileEntity.setEUVar(aEnergy);
+ return true;
+ }
+ }
+
+ public boolean decreaseStoredEU(long aEnergy, boolean aIgnoreTooLessEnergy) {
+ if (!this.canAccessData()) {
+ return false;
+ } else if (this.mMetaTileEntity.getEUVar() - aEnergy < 0L && !aIgnoreTooLessEnergy) {
+ return false;
+ } else {
+ this.setStoredEU(this.mMetaTileEntity.getEUVar() - aEnergy);
+ if (this.mMetaTileEntity.getEUVar() < 0L) {
+ this.setStoredEU(0L);
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ // Required as of 5.09.32-pre5
+ public boolean energyStateReady() {
+ return false;
+ }
+
+ private boolean firstTicked = false;
+
+ public boolean onFirstTick() {
+ if (!firstTicked) {
+ firstTicked = true;
+ if (this.mInventory != null) {
+ this.mInventory.purgeNulls();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds support for the newer function added by
+ * https://github.com/Blood-Asp/GT5-Unofficial/commit/73ee102b63efd92c0f164a7ed7a79ebcd2619617#diff-3051838621d8ae87aa5ccd1345e1f07d
+ */
+ public boolean inputEnergyFrom(byte arg0, boolean arg1) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * Adds support for the newer function added by
+ * https://github.com/Blood-Asp/GT5-Unofficial/commit/73ee102b63efd92c0f164a7ed7a79ebcd2619617#diff-3051838621d8ae87aa5ccd1345e1f07d
+ */
+ public boolean outputsEnergyTo(byte arg0, boolean arg1) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityCircuitProgrammer.java b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityCircuitProgrammer.java
new file mode 100644
index 0000000000..0be6959b8f
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityCircuitProgrammer.java
@@ -0,0 +1,313 @@
+package gtPlusPlus.core.tileentities.general;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.inventories.InventoryCircuitProgrammer;
+import gtPlusPlus.core.recipe.common.CI;
+import gtPlusPlus.core.slots.SlotIntegratedCircuit;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+
+public class TileEntityCircuitProgrammer extends TileEntity implements ISidedInventory {
+
+ private int tickCount = 0;
+ private final InventoryCircuitProgrammer inventoryContents;
+ private String customName;
+ public int locationX;
+ public int locationY;
+ public int locationZ;
+ private int aCurrentMode = 0;
+
+ public TileEntityCircuitProgrammer() {
+ this.inventoryContents = new InventoryCircuitProgrammer();
+ this.setTileLocation();
+ }
+
+ public boolean setTileLocation() {
+ if (this.hasWorldObj()) {
+ if (!this.getWorldObj().isRemote) {
+ this.locationX = this.xCoord;
+ this.locationY = this.yCoord;
+ this.locationZ = this.zCoord;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Rename to hasCircuitToConfigure
+ public final boolean hasCircuitToConfigure() {
+ for (ItemStack i : this.getInventory()
+ .getInventory()) {
+ if (i == null) {
+ continue;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public InventoryCircuitProgrammer getInventory() {
+ return this.inventoryContents;
+ }
+
+ public boolean addOutput() {
+ ItemStack[] aInputs = this.getInventory()
+ .getInventory()
+ .clone();
+ // Check if there is output in slot.
+ Boolean hasOutput = false;
+ if (aInputs[25] != null) {
+ hasOutput = true;
+ }
+ AutoMap<Integer> aValidSlots = new AutoMap<>();
+ int aSlotCount = 0;
+ for (ItemStack i : aInputs) {
+ if (i != null) {
+ aValidSlots.put(aSlotCount);
+ }
+ aSlotCount++;
+ }
+ for (int e : aValidSlots) {
+ boolean doAdd = false;
+ ItemStack g = this.getStackInSlot(e);
+ int aSize = 0;
+ ItemStack aInputStack = null;
+ int aTypeInSlot = SlotIntegratedCircuit.isRegularProgrammableCircuit(g);
+ if (aTypeInSlot >= 0 && g != null) {
+ // No Existing Output
+ if (!hasOutput) {
+ aSize = g.stackSize;
+ doAdd = true;
+ }
+ // Existing Output
+ else {
+ ItemStack f = this.getStackInSlot(25);
+ int aTypeInCheckedSlot = SlotIntegratedCircuit.isRegularProgrammableCircuit(f);
+ // Check that the Circuit in the Output slot is not null and the same type as the circuit input.
+ if (aTypeInCheckedSlot >= 0 && (aTypeInSlot == aTypeInCheckedSlot) && f != null) {
+ if (g.getItem() == f.getItem() && f.getItemDamage() == e) {
+ aSize = f.stackSize + g.stackSize;
+ if (aSize > 64) {
+ aInputStack = g.copy();
+ aInputStack.stackSize = (aSize - 64);
+ }
+ doAdd = true;
+ }
+ }
+ }
+ if (doAdd) {
+ // Check Circuit Type
+ ItemStack aOutput;
+ if (aTypeInSlot == 0) {
+ aOutput = CI.getNumberedCircuit(e);
+ } else if (aTypeInSlot == 1) {
+ aOutput = CI.getNumberedBioCircuit(e);
+ } else if (aTypeInSlot == 2) {
+ aOutput = CI.getNumberedAdvancedCircuit(e);
+ } else {
+ aOutput = null;
+ }
+
+ if (aOutput != null) {
+ aOutput.stackSize = aSize;
+ this.setInventorySlotContents(e, aInputStack);
+ this.setInventorySlotContents(25, aOutput);
+ return true;
+ }
+ }
+ }
+ continue;
+ }
+ return false;
+ }
+
+ @Override
+ public void updateEntity() {
+ try {
+ if (!this.worldObj.isRemote) {
+ if (tickCount % 10 == 0) {
+ if (hasCircuitToConfigure()) {
+ this.addOutput();
+ this.markDirty();
+ }
+ }
+ this.tickCount++;
+ }
+ } catch (final Throwable t) {}
+ }
+
+ public boolean anyPlayerInRange() {
+ return this.worldObj.getClosestPlayer(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D, 32) != null;
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ // Utils.LOG_WARNING("Trying to write NBT data to TE.");
+ final NBTTagCompound chestData = new NBTTagCompound();
+ this.inventoryContents.writeToNBT(chestData);
+ nbt.setTag("ContentsChest", chestData);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ nbt.setInteger("aCurrentMode", aCurrentMode);
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ super.readFromNBT(nbt);
+ // Utils.LOG_WARNING("Trying to read NBT data from TE.");
+ this.inventoryContents.readFromNBT(nbt.getCompoundTag("ContentsChest"));
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+ aCurrentMode = nbt.getInteger("aCurrentMode");
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.getInventory()
+ .getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(final int slot) {
+ return this.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ public ItemStack decrStackSize(final int slot, final int count) {
+ return this.getInventory()
+ .decrStackSize(slot, count);
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(final int slot) {
+ return this.getInventory()
+ .getStackInSlotOnClosing(slot);
+ }
+
+ @Override
+ public void setInventorySlotContents(final int slot, final ItemStack stack) {
+ this.getInventory()
+ .setInventorySlotContents(slot, stack);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.getInventory()
+ .getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(final EntityPlayer entityplayer) {
+ return this.getInventory()
+ .isUseableByPlayer(entityplayer);
+ }
+
+ @Override
+ public void openInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .closeInventory();
+ }
+
+ @Override
+ public boolean isItemValidForSlot(final int slot, final ItemStack itemstack) {
+ return this.getInventory()
+ .isItemValidForSlot(slot, itemstack);
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(final int p_94128_1_) {
+ final int[] accessibleSides = new int[this.getSizeInventory()];
+ for (int r = 0; r < this.getInventory()
+ .getSizeInventory(); r++) {
+ accessibleSides[r] = r;
+ }
+ return accessibleSides;
+ }
+
+ @Override
+ public boolean canInsertItem(final int p_102007_1_, final ItemStack p_102007_2_, final int p_102007_3_) {
+ return p_102007_1_ >= 0 && p_102007_1_ <= 24;
+ }
+
+ @Override
+ public boolean canExtractItem(final int p_102008_1_, final ItemStack p_102008_2_, final int p_102008_3_) {
+ return p_102008_1_ == 25;
+ }
+
+ public String getCustomName() {
+ return this.customName;
+ }
+
+ public void setCustomName(final String customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.customName : "container.circuitprogrammer";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return (this.customName != null) && !this.customName.equals("");
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ final NBTTagCompound tag = new NBTTagCompound();
+ this.writeToNBT(tag);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, this.blockMetadata, tag);
+ }
+
+ @Override
+ public void onDataPacket(final NetworkManager net, final S35PacketUpdateTileEntity pkt) {
+ final NBTTagCompound tag = pkt.func_148857_g();
+ this.readFromNBT(tag);
+ }
+
+ public boolean onScrewdriverRightClick(byte side, EntityPlayer player, int x, int y, int z) {
+ try {
+ if (aCurrentMode == 24) {
+ aCurrentMode = 0;
+ } else {
+ aCurrentMode++;
+ }
+ PlayerUtils.messagePlayer(player, "Now configuring units for type " + aCurrentMode + ".");
+ return true;
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityDecayablesChest.java b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityDecayablesChest.java
new file mode 100644
index 0000000000..b641f2e99e
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityDecayablesChest.java
@@ -0,0 +1,378 @@
+package gtPlusPlus.core.tileentities.general;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.inventories.Inventory_DecayablesChest;
+import gtPlusPlus.core.item.materials.DustDecayable;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class TileEntityDecayablesChest extends TileEntity implements ISidedInventory {
+
+ private final Inventory_DecayablesChest inventoryContents;
+
+ /** Determines if the check for adjacent chests has taken place. */
+ public boolean adjacentChestChecked;
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityDecayablesChest adjacentChestZNeg;
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityDecayablesChest adjacentChestXPos;
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityDecayablesChest adjacentChestXNeg;
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityDecayablesChest adjacentChestZPos;
+ /** The current angle of the lid (between 0 and 1) */
+ public float lidAngle;
+ /** The angle of the lid last tick */
+ public float prevLidAngle;
+ /** The number of players currently using this chest */
+ public int numPlayersUsing;
+
+ private String customName;
+
+ private int cachedChestType;
+ private int tickCount = 0;
+
+ public TileEntityDecayablesChest() {
+ this.inventoryContents = new Inventory_DecayablesChest();
+ }
+
+ public Inventory_DecayablesChest getInventory() {
+ return this.inventoryContents;
+ }
+
+ @Override
+ public void updateEntity() {
+
+ // Try do chesty stuff
+ try {
+ this.updateEntityChest();
+ } catch (Throwable t) {
+
+ }
+
+ try {
+ if (!this.worldObj.isRemote) {
+ this.tickCount++;
+ if ((this.tickCount % 10) == 0) {
+ cachedChestType = 1;
+ }
+
+ if ((this.tickCount % 20) == 0) {
+ for (ItemStack inv : this.getInventory()
+ .getInventory()) {
+ if (inv == null) {
+ continue;
+ }
+ if (inv.getItem() instanceof DustDecayable D) {
+ tryUpdateDecayable(D, inv, this.worldObj);
+ }
+ }
+ }
+ updateSlots();
+ }
+ } catch (final Throwable t) {}
+ }
+
+ public void tryUpdateDecayable(final DustDecayable b, ItemStack iStack, final World world) {
+ if (world == null || iStack == null) {
+ return;
+ }
+ if (world.isRemote) {
+ return;
+ }
+
+ boolean a1, a2;
+ int u = 0;
+ a1 = b.isTicking(world, iStack);
+ a2 = false;
+ int SECONDS_TO_PROCESS = 1;
+ while (u < (20 * SECONDS_TO_PROCESS)) {
+ if (!a1) {
+ break;
+ }
+ a1 = b.isTicking(world, iStack);
+ a2 = b.tickItemTag(world, iStack);
+ u++;
+ }
+ Logger.MACHINE_INFO("| " + b.getUnlocalizedName() + " | " + a1 + "/" + a2);
+
+ if (!a1 && !a2) {
+ ItemStack replacement = ItemUtils.getSimpleStack(b.getDecayResult());
+ replacement.stackSize = 1;
+ // iStack = replacement.copy();
+ for (int fff = 0; fff < this.inventoryContents.getSizeInventory(); fff++) {
+ if (this.inventoryContents.getStackInSlot(fff) == iStack) {
+ this.inventoryContents.setInventorySlotContents(fff, replacement.copy());
+ }
+ }
+
+ updateSlots();
+ this.inventoryContents.markDirty();
+ }
+ }
+
+ public boolean anyPlayerInRange() {
+ return this.worldObj.getClosestPlayer(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D, 32) != null;
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ // Utils.LOG_WARNING("Trying to write NBT data to TE.");
+ final NBTTagCompound chestData = new NBTTagCompound();
+ this.inventoryContents.writeToNBT(chestData);
+ nbt.setTag("ContentsChest", chestData);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ super.readFromNBT(nbt);
+ // Utils.LOG_WARNING("Trying to read NBT data from TE.");
+ this.inventoryContents.readFromNBT(nbt.getCompoundTag("ContentsChest"));
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.getInventory()
+ .getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(final int slot) {
+ return this.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ public ItemStack decrStackSize(final int slot, final int count) {
+ return this.getInventory()
+ .decrStackSize(slot, count);
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(final int slot) {
+ return this.getInventory()
+ .getStackInSlotOnClosing(slot);
+ }
+
+ @Override
+ public void setInventorySlotContents(final int slot, final ItemStack stack) {
+ this.getInventory()
+ .setInventorySlotContents(slot, stack);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.getInventory()
+ .getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(final EntityPlayer entityplayer) {
+ return this.getInventory()
+ .isUseableByPlayer(entityplayer);
+ }
+
+ @Override
+ public void openInventory() {
+ if (this.numPlayersUsing < 0) {
+ this.numPlayersUsing = 0;
+ }
+ if (!this.worldObj.isRemote) {
+ this.numPlayersUsing++;
+ cachedChestType = 1;
+ }
+ this.worldObj
+ .addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, this.numPlayersUsing);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ if (!this.worldObj.isRemote) {
+ this.numPlayersUsing--;
+ cachedChestType = 1;
+ }
+ this.worldObj
+ .addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, this.numPlayersUsing);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .closeInventory();
+ }
+
+ @Override
+ public boolean isItemValidForSlot(final int slot, final ItemStack itemstack) {
+ return this.getInventory()
+ .isItemValidForSlot(slot, itemstack);
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(final int p_94128_1_) {
+ final int[] accessibleSides = new int[this.getSizeInventory()];
+ for (int r = 0; r < this.getInventory()
+ .getSizeInventory(); r++) {
+ accessibleSides[r] = r;
+ }
+ return accessibleSides;
+ }
+
+ @Override
+ public boolean canInsertItem(final int p_102007_1_, final ItemStack p_102007_2_, final int p_102007_3_) {
+ return this.getInventory()
+ .isItemValidForSlot(0, p_102007_2_);
+ }
+
+ @Override
+ public boolean canExtractItem(final int p_102008_1_, final ItemStack p_102008_2_, final int p_102008_3_) {
+ return this.getInventory()
+ .isItemValidForSlot(0, p_102008_2_);
+ }
+
+ public String getCustomName() {
+ return this.customName;
+ }
+
+ public void setCustomName(final String customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.customName : "container.DecayablesChest";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return (this.customName != null) && !this.customName.equals("");
+ }
+
+ /**
+ * Causes the TileEntity to reset all it's cached values for it's container Block, metadata and in the case of
+ * chests, the adjacent chest check
+ */
+ @Override
+ public void updateContainingBlockInfo() {
+ super.updateContainingBlockInfo();
+ this.adjacentChestChecked = false;
+ }
+
+ /**
+ * Performs the check for adjacent chests to determine if this chest is double or not.
+ */
+ public void checkForAdjacentChests() {
+ if (!this.adjacentChestChecked) {
+ this.adjacentChestChecked = true;
+ this.adjacentChestZNeg = null;
+ this.adjacentChestXPos = null;
+ this.adjacentChestXNeg = null;
+ this.adjacentChestZPos = null;
+ }
+ }
+
+ public void updateEntityChest() {
+ float f;
+ this.prevLidAngle = this.lidAngle;
+ f = 0.04F;
+ double d2;
+ if (this.numPlayersUsing > 0 && this.lidAngle == 0.0F
+ && this.adjacentChestZNeg == null
+ && this.adjacentChestXNeg == null) {
+ double d1 = (double) this.xCoord + 0.5D;
+ d2 = (double) this.zCoord + 0.5D;
+ this.worldObj.playSoundEffect(
+ d1,
+ (double) this.yCoord + 0.5D,
+ d2,
+ "random.chestopen",
+ 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.numPlayersUsing == 0 && this.lidAngle > 0.0F || this.numPlayersUsing > 0 && this.lidAngle < 1.0F) {
+ float f1 = this.lidAngle;
+ if (this.numPlayersUsing > 0) {
+ // this.lidAngle += f;
+ this.lidAngle += (float) (f * (1 + 0.10 * 0.01));
+ } else {
+ // this.lidAngle -= f;
+ this.lidAngle -= (float) (f * (1 + 0.10 * 0.01));
+ }
+ if (this.lidAngle > 1.0F) {
+ this.lidAngle = 1.0F;
+ }
+ float f2 = 0.5F;
+ if (this.lidAngle < f2 && f1 >= f2 && this.adjacentChestZNeg == null && this.adjacentChestXNeg == null) {
+ d2 = (double) this.xCoord + 0.5D;
+ double d0 = (double) this.zCoord + 0.5D;
+ this.worldObj.playSoundEffect(
+ d2,
+ (double) this.yCoord + 0.5D,
+ d0,
+ "random.chestclosed",
+ 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.lidAngle < 0.0F) {
+ this.lidAngle = 0.0F;
+ }
+ }
+ }
+
+ /**
+ * Called when a client event is received with the event number and argument, see World.sendClientEvent
+ */
+ @Override
+ public boolean receiveClientEvent(int p_145842_1_, int p_145842_2_) {
+ if (p_145842_1_ == 1) {
+ this.numPlayersUsing = p_145842_2_;
+ return true;
+ } else {
+ return super.receiveClientEvent(p_145842_1_, p_145842_2_);
+ }
+ }
+
+ /**
+ * invalidates a tile entity
+ */
+ @Override
+ public final void invalidate() {
+ super.invalidate();
+ cachedChestType = 1;
+ this.updateContainingBlockInfo();
+ this.checkForAdjacentChests();
+ }
+
+ private int updateSlots() {
+ // Have slots changed?
+ if (cachedChestType == 0) {
+ return 0;
+ }
+ ItemUtils.organiseInventory(getInventory());
+ cachedChestType = 0;
+ return cachedChestType;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityFishTrap.java b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityFishTrap.java
new file mode 100644
index 0000000000..1a09b6b423
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityFishTrap.java
@@ -0,0 +1,294 @@
+package gtPlusPlus.core.tileentities.general;
+
+import static gregtech.api.enums.Mods.PamsHarvestCraft;
+
+import java.util.Random;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.FishingHooks;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.block.ModBlocks;
+import gtPlusPlus.core.inventories.InventoryFishTrap;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class TileEntityFishTrap extends TileEntity implements ISidedInventory {
+
+ private int tickCount = 0;
+ private final InventoryFishTrap inventoryContents;
+ private String customName;
+ // The number of water blocks is used as an index to get the tick rate.
+ private final static short[] waterBlocksToTickRate = new short[] { 0, 0, 5600, 4400, 3200, 2000, 1750 };
+ private int surroundingWaterBlocks = 0;
+
+ public TileEntityFishTrap() {
+ this.inventoryContents = new InventoryFishTrap();
+ }
+
+ private int getNumberOfSurroundingWater() {
+ if (!this.hasWorldObj() || this.getWorldObj().isRemote) {
+ return 0;
+ }
+ final Block[] surroundingBlocks = new Block[6];
+ surroundingBlocks[0] = this.worldObj.getBlock(this.xCoord, this.yCoord + 1, this.zCoord); // Above
+ surroundingBlocks[1] = this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord); // Below
+ surroundingBlocks[2] = this.worldObj.getBlock(this.xCoord + 1, this.yCoord, this.zCoord);
+ surroundingBlocks[3] = this.worldObj.getBlock(this.xCoord - 1, this.yCoord, this.zCoord);
+ surroundingBlocks[4] = this.worldObj.getBlock(this.xCoord, this.yCoord, this.zCoord + 1);
+ surroundingBlocks[5] = this.worldObj.getBlock(this.xCoord, this.yCoord, this.zCoord - 1);
+ int waterCount = 0;
+ int trapCount = 0;
+ for (final Block checkBlock : surroundingBlocks) {
+ if (checkBlock == ModBlocks.blockFishTrap) {
+ trapCount++;
+ } else if ((checkBlock == Blocks.water) || (checkBlock == Blocks.flowing_water)) {
+ waterCount++;
+ }
+ }
+ // Explicitly check for at least 2 water blocks.
+ if (waterCount < 2) {
+ return 0;
+ }
+ // Only allow the first four traps to count towards valid neighbor blocks.
+ return waterCount + Math.min(trapCount, 4);
+ }
+
+ public InventoryFishTrap getInventory() {
+ return this.inventoryContents;
+ }
+
+ private void tryAddLoot() {
+ ItemUtils.organiseInventory(getInventory());
+ final ItemStack loot = this.generateLootForFishTrap();
+ if (loot == null) {
+ return;
+ }
+ for (final ItemStack contents : this.getInventory()
+ .getInventory()) {
+ if (GT_Utility.areStacksEqual(loot, contents)) {
+ if (contents.stackSize < contents.getMaxStackSize()) {
+ contents.stackSize++;
+ this.markDirty();
+ return;
+ }
+ }
+ }
+ int checkingSlot = 0;
+ for (final ItemStack contents : this.getInventory()
+ .getInventory()) {
+ if (contents == null) {
+ this.getInventory()
+ .setInventorySlotContents(checkingSlot, loot);
+ this.markDirty();
+ return;
+ }
+ checkingSlot++;
+ }
+ }
+
+ @Nullable
+ private ItemStack generateLootForFishTrap() {
+ final int lootWeight = MathUtils.randInt(0, 100);
+ ItemStack loot = null;
+ if (lootWeight <= 5) {
+ loot = ItemUtils.getSimpleStack(Items.slime_ball);
+ } else if (lootWeight <= 10) {
+ loot = ItemUtils.getSimpleStack(Items.bone);
+ } else if (lootWeight <= 15) {
+ loot = ItemUtils.getSimpleStack(Blocks.sand);
+ } else if (lootWeight <= 20) {
+ loot = ItemUtils.simpleMetaStack(Items.dye, 0, 1);
+ }
+ // Junk Loot
+ else if (lootWeight <= 23) {
+ if (PamsHarvestCraft.isModLoaded()) {
+ loot = ItemUtils.getItemStackOfAmountFromOreDictNoBroken("cropSeaweed", 1);
+ } else {
+ loot = ItemUtils.getSimpleStack(Blocks.dirt);
+ }
+ }
+ // Pam Fish
+ else if (lootWeight <= 99) {
+ final Random xstr = new Random();
+ loot = FishingHooks.getRandomFishable(xstr, 100);
+ } else if (lootWeight == 100) {
+ final int rareLoot = MathUtils.randInt(1, 10);
+ if (rareLoot <= 4) {
+ loot = Materials.Iron.getNuggets(1);
+ } else if (rareLoot <= 7) {
+ loot = ItemUtils.getSimpleStack(Items.gold_nugget);
+ } else if (rareLoot <= 9) {
+ loot = ItemUtils.getSimpleStack(Items.emerald);
+ } else {
+ loot = ItemUtils.getSimpleStack(Items.diamond);
+ }
+ }
+ if (loot != null) {
+ loot.stackSize = 1;
+ }
+ return loot;
+ }
+
+ @Override
+ public void updateEntity() {
+ if (this.worldObj.isRemote) {
+ return;
+ }
+
+ this.tickCount++;
+ // Only recalculate the amount of neighboring water/trap blocks every 20 ticks.
+ if ((this.tickCount % 20) == 0) {
+ this.surroundingWaterBlocks = getNumberOfSurroundingWater();
+ }
+
+ if ((waterBlocksToTickRate[this.surroundingWaterBlocks] != 0)
+ && this.tickCount > waterBlocksToTickRate[this.surroundingWaterBlocks]) {
+ int aExtraLootChance = MathUtils.randInt(1, 1000);
+ if (aExtraLootChance >= 999) {
+ this.tryAddLoot();
+ this.tryAddLoot();
+ this.tryAddLoot();
+ } else {
+ this.tryAddLoot();
+ }
+ this.markDirty();
+
+ this.tickCount = 0;
+ }
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ final NBTTagCompound chestData = new NBTTagCompound();
+ this.inventoryContents.writeToNBT(chestData);
+ nbt.setTag("ContentsChest", chestData);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ super.readFromNBT(nbt);
+ this.inventoryContents.readFromNBT(nbt.getCompoundTag("ContentsChest"));
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.getInventory()
+ .getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(final int slot) {
+ return this.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ public ItemStack decrStackSize(final int slot, final int count) {
+ return this.getInventory()
+ .decrStackSize(slot, count);
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(final int slot) {
+ return this.getInventory()
+ .getStackInSlotOnClosing(slot);
+ }
+
+ @Override
+ public void setInventorySlotContents(final int slot, final ItemStack stack) {
+ this.getInventory()
+ .setInventorySlotContents(slot, stack);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.getInventory()
+ .getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(final EntityPlayer entityplayer) {
+ return this.getInventory()
+ .isUseableByPlayer(entityplayer);
+ }
+
+ @Override
+ public void openInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .closeInventory();
+ }
+
+ @Override
+ public boolean isItemValidForSlot(final int slot, final ItemStack itemstack) {
+ return this.getInventory()
+ .isItemValidForSlot(slot, itemstack);
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(final int p_94128_1_) {
+ final int[] accessibleSides = new int[this.getSizeInventory()];
+ for (int r = 0; r < this.getInventory()
+ .getSizeInventory(); r++) {
+ accessibleSides[r] = r;
+ }
+ return accessibleSides;
+ }
+
+ @Override
+ public boolean canInsertItem(final int p_102007_1_, final ItemStack p_102007_2_, final int p_102007_3_) {
+ return false;
+ }
+
+ @Override
+ public boolean canExtractItem(final int p_102008_1_, final ItemStack p_102008_2_, final int p_102008_3_) {
+ return true;
+ }
+
+ public String getCustomName() {
+ return this.customName;
+ }
+
+ public void setCustomName(final String customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.customName : "container.fishtrap";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return (this.customName != null) && !this.customName.isEmpty();
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityInfiniteFluid.java b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityInfiniteFluid.java
new file mode 100644
index 0000000000..fd528c589d
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityInfiniteFluid.java
@@ -0,0 +1,148 @@
+package gtPlusPlus.core.tileentities.general;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidEvent;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTank;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+public class TileEntityInfiniteFluid extends TileEntity implements IFluidHandler {
+
+ public FluidTank tank = new FluidTank(Integer.MAX_VALUE);
+ private boolean needsUpdate = false;
+ private int updateTimer = 0;
+
+ public TileEntityInfiniteFluid() {}
+
+ @Override
+ public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
+ needsUpdate = true;
+ return this.tank.fill(resource, doFill);
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
+ needsUpdate = true;
+ return this.tank.drain(resource.amount, doDrain);
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
+ needsUpdate = true;
+ FluidStack fluid = this.tank.getFluid();
+ // return this.tank.drain(maxDrain, doDrain);
+ if (fluid == null) {
+ return null;
+ }
+
+ int drained = maxDrain;
+ if (fluid.amount < drained) {
+ drained = fluid.amount;
+ }
+
+ FluidStack stack = new FluidStack(fluid, drained);
+ if (doDrain) {
+ fluid.amount -= drained;
+ if (fluid.amount <= 0) {
+ fluid = null;
+ }
+
+ if (this != null) {
+ FluidEvent.fireEvent(
+ new FluidEvent.FluidDrainingEvent(
+ fluid,
+ this.getWorldObj(),
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ this.tank,
+ 0));
+ }
+ }
+ return stack;
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection from, Fluid fluid) {
+ return true;
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection from, Fluid fluid) {
+ return true;
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection from) {
+ return new FluidTankInfo[] { this.tank.getInfo() };
+ }
+
+ public float getAdjustedVolume() {
+ needsUpdate = true;
+ float amount = tank.getFluidAmount();
+ float capacity = tank.getCapacity();
+ float volume = (amount / capacity) * 0.8F;
+ return volume;
+ }
+
+ @Override
+ public void updateEntity() {
+
+ if (this.tank.getFluid() != null) {
+ FluidStack bigStorage = this.tank.getFluid();
+ bigStorage.amount = this.tank.getCapacity();
+ this.tank.setFluid(bigStorage);
+ }
+
+ if (needsUpdate) {
+
+ if (this.tank.getFluid() != null) {
+ FluidStack bigStorage = this.tank.getFluid();
+ bigStorage.amount = this.tank.getCapacity();
+ this.tank.setFluid(bigStorage);
+ }
+
+ if (updateTimer == 0) {
+ updateTimer = 10; // every 10 ticks it will send an update
+ } else {
+ --updateTimer;
+ if (updateTimer == 0) {
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ needsUpdate = false;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound tag) {
+ tank.readFromNBT(tag);
+ super.readFromNBT(tag);
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound tag) {
+ tank.writeToNBT(tag);
+ super.writeToNBT(tag);
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ NBTTagCompound tag = new NBTTagCompound();
+ writeToNBT(tag);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, this.blockMetadata, tag);
+ }
+
+ @Override
+ public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
+ NBTTagCompound tag = pkt.func_148857_g();
+ readFromNBT(tag);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityVolumetricFlaskSetter.java b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityVolumetricFlaskSetter.java
new file mode 100644
index 0000000000..a9bc2b0049
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/general/TileEntityVolumetricFlaskSetter.java
@@ -0,0 +1,418 @@
+package gtPlusPlus.core.tileentities.general;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.fluids.FluidStack;
+
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.container.Container_VolumetricFlaskSetter;
+import gtPlusPlus.core.inventories.Inventory_VolumetricFlaskSetter;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+import gtPlusPlus.xmod.gregtech.common.helpers.VolumetricFlaskHelper;
+
+public class TileEntityVolumetricFlaskSetter extends TileEntity implements ISidedInventory {
+
+ private int tickCount = 0;
+ private final Inventory_VolumetricFlaskSetter inventoryContents;
+ private String customName;
+ public int locationX;
+ public int locationY;
+ public int locationZ;
+ private int aCurrentMode = 0;
+ private int aCustomValue = 1000;
+
+ public TileEntityVolumetricFlaskSetter() {
+ this.inventoryContents = new Inventory_VolumetricFlaskSetter();
+ this.setTileLocation();
+ }
+
+ public int getCustomValue() {
+ // Logger.INFO("Value: "+this.aCustomValue);
+ return this.aCustomValue;
+ }
+
+ public void setCustomValue(int aVal) {
+ log("Old Value: " + this.aCustomValue);
+ this.aCustomValue = (short) MathUtils.balance(aVal, 0, Short.MAX_VALUE);
+ log("New Value: " + this.aCustomValue);
+ markDirty();
+ }
+
+ public boolean setTileLocation() {
+ if (this.hasWorldObj()) {
+ if (!this.getWorldObj().isRemote) {
+ this.locationX = this.xCoord;
+ this.locationY = this.yCoord;
+ this.locationZ = this.zCoord;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Rename to hasCircuitToConfigure
+ public final boolean hasFlask() {
+ for (int i = 0; i < this.getInventory()
+ .getInventory().length - 1; i++) {
+ if (i == Container_VolumetricFlaskSetter.SLOT_OUTPUT) {
+ continue;
+ }
+ if (this.getInventory()
+ .getInventory()[i] != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Inventory_VolumetricFlaskSetter getInventory() {
+ return this.inventoryContents;
+ }
+
+ private int getFlaskType(ItemStack aStack) {
+ if (VolumetricFlaskHelper.isNormalVolumetricFlask(aStack)) {
+ return 1;
+ } else if (VolumetricFlaskHelper.isLargeVolumetricFlask(aStack)) {
+ return 2;
+ } else if (VolumetricFlaskHelper.isGiganticVolumetricFlask(aStack)) {
+ return 3;
+ }
+ return 0;
+ }
+
+ private int getCapacityForSlot(int aSlot) {
+ return switch (aSlot) {
+ case 0 -> // 16
+ 16;
+ case 1 -> // 36
+ 36;
+ case 2 -> // 144
+ 144;
+ case 3 -> // 432
+ 432;
+ case 4 -> // 576
+ 576;
+ case 5 -> // 720
+ 720;
+ case 6 -> // 864
+ 864;
+ case 7 -> // Custom
+ getCustomValue();
+ default -> 1000;
+ };
+ }
+
+ public boolean addOutput() {
+
+ // Don't do anything unless we have items
+ if (!hasFlask()) {
+ Logger.INFO("No Flasks.");
+ return false;
+ }
+
+ ItemStack[] aInputs = this.getInventory()
+ .getInventory()
+ .clone();
+
+ // Check if there is output in slot.
+ Boolean hasOutput = false;
+ if (aInputs[Container_VolumetricFlaskSetter.SLOT_OUTPUT] != null) {
+ hasOutput = true;
+ if (aInputs[Container_VolumetricFlaskSetter.SLOT_OUTPUT].stackSize >= 16) {
+ return false;
+ }
+ }
+ AutoMap<Integer> aValidSlots = new AutoMap<>();
+ int aSlotCount = 0;
+ for (ItemStack i : aInputs) {
+ if (i != null) {
+ aValidSlots.put(aSlotCount);
+ }
+ aSlotCount++;
+ }
+ for (int e : aValidSlots) {
+
+ // Skip slot 7 (Custom) unless it has a value > 0
+ if (e == 7 && getCustomValue() <= 0) {
+ log("Skipping Custom slot as value <= 0");
+ continue;
+ }
+ if (e == Container_VolumetricFlaskSetter.SLOT_OUTPUT) {
+ continue;
+ }
+
+ boolean doAdd = false;
+ ItemStack g = this.getStackInSlot(e);
+ FluidStack aInputFluidStack = VolumetricFlaskHelper.getFlaskFluid(g);
+ int aSize = 0;
+ ItemStack aInputStack = null;
+ int aTypeInSlot = getFlaskType(g);
+ if (aTypeInSlot > 0 && g != null) {
+ // No Existing Output
+ if (!hasOutput) {
+ aSize = g.stackSize;
+ doAdd = true;
+ }
+ // Existing Output
+ else {
+ ItemStack f = aInputs[Container_VolumetricFlaskSetter.SLOT_OUTPUT];
+ FluidStack aFluidInCheckedSlot = VolumetricFlaskHelper.getFlaskFluid(f);
+ int aTypeInCheckedSlot = getFlaskType(f);
+ // Check that the Circuit in the Output slot is not null and the same type as the circuit input.
+ if (aTypeInCheckedSlot > 0 && (aTypeInSlot == aTypeInCheckedSlot) && f != null) {
+ if (g.getItem() == f.getItem()
+ && VolumetricFlaskHelper.getFlaskCapacity(f) == getCapacityForSlot(e)
+ && ((aInputFluidStack == null && aFluidInCheckedSlot == null)
+ || aInputFluidStack.isFluidEqual(aFluidInCheckedSlot))) {
+ log(
+ "Input Slot Flask Contains: "
+ + (aInputFluidStack != null ? aInputFluidStack.getLocalizedName() : "Empty"));
+ log(
+ "Output Slot Flask Contains: "
+ + (aFluidInCheckedSlot != null ? aFluidInCheckedSlot.getLocalizedName() : "Empty"));
+ aSize = f.stackSize + g.stackSize;
+ if (aSize > 16) {
+ aInputStack = g.copy();
+ aInputStack.stackSize = (aSize - 16);
+ }
+ doAdd = true;
+ }
+ }
+ }
+ if (doAdd) {
+ // Check Circuit Type
+ ItemStack aOutput;
+ FluidStack aOutputFluid = null;
+ if (!VolumetricFlaskHelper.isFlaskEmpty(g)) {
+ aOutputFluid = aInputFluidStack.copy();
+ }
+ if (aTypeInSlot == 1) {
+ aOutput = VolumetricFlaskHelper.getVolumetricFlask(1);
+ } else if (aTypeInSlot == 2) {
+ aOutput = VolumetricFlaskHelper.getLargeVolumetricFlask(1);
+ } else if (aTypeInSlot == 3) {
+ aOutput = VolumetricFlaskHelper.getGiganticVolumetricFlask(1);
+ } else {
+ aOutput = null;
+ }
+ if (aOutput != null) {
+ aOutput.stackSize = aSize;
+ int aCapacity = getCapacityForSlot(e);
+ VolumetricFlaskHelper.setNewFlaskCapacity(aOutput, aCapacity);
+ if (aOutputFluid != null) {
+ if (aOutputFluid.amount > aCapacity) {
+ aOutputFluid.amount = aCapacity;
+ }
+ VolumetricFlaskHelper.setFluid(aOutput, aOutputFluid);
+ }
+ this.setInventorySlotContents(e, aInputStack);
+ this.setInventorySlotContents(Container_VolumetricFlaskSetter.SLOT_OUTPUT, aOutput);
+ return true;
+ }
+ }
+ }
+ continue;
+ }
+ return false;
+ }
+
+ @Override
+ public void updateEntity() {
+ try {
+ if (!this.worldObj.isRemote) {
+ if (tickCount % 10 == 0) {
+ if (hasFlask()) {
+ this.addOutput();
+ this.markDirty();
+ }
+ }
+ this.tickCount++;
+ }
+ } catch (final Throwable t) {}
+ }
+
+ public boolean anyPlayerInRange() {
+ return this.worldObj.getClosestPlayer(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D, 32) != null;
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ // Utils.LOG_WARNING("Trying to write NBT data to TE.");
+ final NBTTagCompound chestData = new NBTTagCompound();
+ this.inventoryContents.writeToNBT(chestData);
+ nbt.setTag("ContentsChest", chestData);
+ nbt.setInteger("aCustomValue", aCustomValue);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ nbt.setInteger("aCurrentMode", aCurrentMode);
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ super.readFromNBT(nbt);
+ // Utils.LOG_WARNING("Trying to read NBT data from TE.");
+ this.inventoryContents.readFromNBT(nbt.getCompoundTag("ContentsChest"));
+ this.aCustomValue = nbt.getInteger("aCustomValue");
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+ aCurrentMode = nbt.getInteger("aCurrentMode");
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.getInventory()
+ .getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(final int slot) {
+ return this.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ public ItemStack decrStackSize(final int slot, final int count) {
+ return this.getInventory()
+ .decrStackSize(slot, count);
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(final int slot) {
+ return this.getInventory()
+ .getStackInSlotOnClosing(slot);
+ }
+
+ @Override
+ public void setInventorySlotContents(final int slot, final ItemStack stack) {
+ this.getInventory()
+ .setInventorySlotContents(slot, stack);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.getInventory()
+ .getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(final EntityPlayer entityplayer) {
+ return this.getInventory()
+ .isUseableByPlayer(entityplayer);
+ }
+
+ @Override
+ public void openInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .closeInventory();
+ }
+
+ @Override
+ public boolean isItemValidForSlot(final int slot, final ItemStack itemstack) {
+ return this.getInventory()
+ .isItemValidForSlot(slot, itemstack);
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(final int p_94128_1_) {
+ final int[] accessibleSides = new int[this.getSizeInventory()];
+ for (int r = 0; r < this.getInventory()
+ .getSizeInventory(); r++) {
+ accessibleSides[r] = r;
+ }
+ return accessibleSides;
+ }
+
+ @Override
+ public boolean canInsertItem(final int aSlot, final ItemStack p_102007_2_, final int p_102007_3_) {
+ return aSlot == aCurrentMode;
+ }
+
+ @Override
+ public boolean canExtractItem(final int aSlot, final ItemStack p_102008_2_, final int p_102008_3_) {
+ return aSlot == Container_VolumetricFlaskSetter.SLOT_OUTPUT;
+ }
+
+ public String getCustomName() {
+ return this.customName;
+ }
+
+ public void setCustomName(final String customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.customName : "container.VolumetricFlaskSetter";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return (this.customName != null) && !this.customName.equals("");
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ final NBTTagCompound tag = new NBTTagCompound();
+ this.writeToNBT(tag);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, this.blockMetadata, tag);
+ }
+
+ @Override
+ public void onDataPacket(final NetworkManager net, final S35PacketUpdateTileEntity pkt) {
+ final NBTTagCompound tag = pkt.func_148857_g();
+ this.readFromNBT(tag);
+ }
+
+ public boolean onScrewdriverRightClick(byte side, EntityPlayer player, int x, int y, int z) {
+
+ if (player.isSneaking()) {
+ PlayerUtils.messagePlayer(player, "Value: " + this.getCustomValue());
+ }
+
+ try {
+ if (aCurrentMode == 7) {
+ aCurrentMode = 0;
+ } else {
+ aCurrentMode++;
+ }
+ PlayerUtils.messagePlayer(player, "Slot " + aCurrentMode + " is now default.");
+ return true;
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+
+ public void log(String aString) {
+ Logger.INFO("[Flask-Tile] " + aString);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityAdvPooCollector.java b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityAdvPooCollector.java
new file mode 100644
index 0000000000..5e0aaf8370
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityAdvPooCollector.java
@@ -0,0 +1,140 @@
+package gtPlusPlus.core.tileentities.machines;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.passive.EntityAnimal;
+import net.minecraft.entity.passive.EntityChicken;
+import net.minecraft.entity.passive.EntityCow;
+import net.minecraft.entity.passive.EntityHorse;
+import net.minecraft.entity.passive.EntityMooshroom;
+import net.minecraft.entity.passive.EntitySheep;
+import net.minecraft.entity.passive.EntityVillager;
+import net.minecraft.entity.passive.IAnimals;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.item.chemistry.AgriculturalChem;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class TileEntityAdvPooCollector extends TileEntityBaseFluidCollector {
+
+ public TileEntityAdvPooCollector() {
+ super(18, 128000);
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection from, Fluid fluid) {
+ return false;
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection from, Fluid fluid) {
+ return true;
+ }
+
+ @Override
+ public void onPreLogicTick() {}
+
+ @Override
+ public <V> boolean addDrop(V aPooMaker) {
+ int aChance = MathUtils.randInt(0, 50000);
+ if (aChance > 0) {
+ ItemStack aPoop;
+ if (aChance <= 200) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustManureByproducts", 1);
+ } else if (aChance <= 1000) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustSmallManureByproducts", 1);
+ } else if (aChance <= 2000) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustTinyManureByproducts", 1);
+ } else {
+ return false;
+ }
+
+ // Add to inventory if not full, else espawn in world
+ if (!this.mInventory.addItemStack(aPoop)) {
+ EntityItem entity = new EntityItem(worldObj, xCoord, yCoord + 1.5, zCoord, aPoop);
+ worldObj.spawnEntityInWorld(entity);
+ }
+ }
+
+ return false;
+ }
+
+ private static AutoMap<Class> aEntityToDrain = new AutoMap<>();
+
+ @Override
+ public AutoMap<Class> aThingsToLookFor() {
+ if (aEntityToDrain.isEmpty()) {
+ aEntityToDrain.add(EntityAnimal.class);
+ aEntityToDrain.add(IAnimals.class);
+ aEntityToDrain.add(EntityVillager.class);
+ aEntityToDrain.add(EntityPlayer.class);
+ }
+ return aEntityToDrain;
+ }
+
+ @Override
+ public <V> int onPostTick(V aPooMaker) {
+ if (this.tank.getFluidAmount() < this.tank.getCapacity()) {
+ int aPooAmount = 0;
+ // Vanilla Animals
+ if (aPooMaker instanceof EntityChicken) {
+ aPooAmount = MathUtils.randInt(1, 40);
+ } else if (aPooMaker instanceof EntityHorse) {
+ aPooAmount = MathUtils.randInt(20, 40);
+ } else if (aPooMaker instanceof EntityCow) {
+ aPooAmount = MathUtils.randInt(18, 45);
+ } else if (aPooMaker instanceof EntityMooshroom) {
+ aPooAmount = 17;
+ } else if (aPooMaker instanceof EntitySheep) {
+ aPooAmount = MathUtils.randInt(8, 30);
+ } else {
+ if (aPooMaker instanceof EntityAnimal || aPooMaker instanceof IAnimals) {
+ aPooAmount = MathUtils.randInt(5, 35);
+ } else if (aPooMaker instanceof EntityVillager) {
+ aPooAmount = MathUtils.randInt(25, 30);
+ } else if (aPooMaker instanceof EntityPlayer) {
+ aPooAmount = MathUtils.randInt(1, 3);
+ } else {
+ aPooAmount = MathUtils.randInt(1, 10);
+ }
+ }
+ aPooAmount = Math.max(Math.min(this.tank.getCapacity() - this.tank.getFluidAmount(), aPooAmount), 1);
+ return Math.max(
+ 1,
+ (aPooAmount
+ * MathUtils
+ .getRandomFromArray(new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4 })
+ / 10));
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public Fluid fluidToProvide() {
+ return AgriculturalChem.PoopJuice;
+ }
+
+ @Override
+ public ItemStack itemToSpawnInWorldIfTankIsFull() {
+ int a = MathUtils.randInt(0, 75);
+ ItemStack aItem = null;
+ if (a <= 30) {
+ aItem = ItemUtils.getSimpleStack(AgriculturalChem.dustDirt);
+ } else if (a <= 40) {
+ aItem = ItemUtils.getItemStackOfAmountFromOreDict("dustManureByproducts", 1);
+ } else if (a <= 55) {
+ aItem = ItemUtils.getItemStackOfAmountFromOreDict("dustSmallManureByproducts", 1);
+ }
+ return aItem;
+ }
+
+ @Override
+ public int getBaseTickRate() {
+ return MathUtils.randInt(50, 200);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityBaseFluidCollector.java b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityBaseFluidCollector.java
new file mode 100644
index 0000000000..6340415e82
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityBaseFluidCollector.java
@@ -0,0 +1,241 @@
+package gtPlusPlus.core.tileentities.machines;
+
+import java.util.List;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidEvent;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTank;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.api.objects.minecraft.BTF_FluidTank;
+import gtPlusPlus.api.objects.minecraft.BlockPos;
+import gtPlusPlus.core.tileentities.base.TileEntityBase;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public abstract class TileEntityBaseFluidCollector extends TileEntityBase implements IFluidHandler {
+
+ public final FluidTank tank;
+ private boolean needsUpdate = false;
+ private int updateTimer = 0;
+ private long internalTickCounter = 0;
+ private BlockPos internalBlockLocation;
+
+ public TileEntityBaseFluidCollector(int aInvSlotCount, int aTankCapcity) {
+ super(aInvSlotCount);
+ tank = new BTF_FluidTank(aTankCapcity);
+ }
+
+ @Override
+ public final int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
+ needsUpdate = true;
+ return this.tank.fill(resource, doFill);
+ }
+
+ @Override
+ public final FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
+ needsUpdate = true;
+ return this.tank.drain(resource.amount, doDrain);
+ }
+
+ @Override
+ public final FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
+ needsUpdate = true;
+ FluidStack fluid = this.tank.getFluid();
+ // return this.tank.drain(maxDrain, doDrain);
+ if (fluid == null) {
+ return null;
+ }
+
+ int drained = maxDrain;
+ if (fluid.amount < drained) {
+ drained = fluid.amount;
+ }
+
+ FluidStack stack = new FluidStack(fluid, drained);
+ if (doDrain) {
+ fluid.amount -= drained;
+ if (fluid.amount <= 0) {
+ fluid = null;
+ }
+
+ if (this != null) {
+ FluidEvent.fireEvent(
+ new FluidEvent.FluidDrainingEvent(
+ fluid,
+ this.getWorldObj(),
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ this.tank,
+ 0));
+ }
+ }
+ return stack;
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection from, Fluid fluid) {
+ return false;
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection from, Fluid fluid) {
+ return true;
+ }
+
+ @Override
+ public final FluidTankInfo[] getTankInfo(ForgeDirection from) {
+ return new FluidTankInfo[] { this.tank.getInfo() };
+ }
+
+ @Override
+ public final void updateEntity() {
+ super.updateEntity();
+ onPreLogicTick();
+ logicTick();
+ if (needsUpdate) {
+ if (updateTimer == 0) {
+ updateTimer = 10; // every 10 ticks it will send an update
+ } else {
+ --updateTimer;
+ if (updateTimer == 0) {
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ needsUpdate = false;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound tag) {
+ tank.readFromNBT(tag);
+ super.readFromNBT(tag);
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound tag) {
+ tank.writeToNBT(tag);
+ super.writeToNBT(tag);
+ }
+
+ @Override
+ public final Packet getDescriptionPacket() {
+ NBTTagCompound tag = new NBTTagCompound();
+ writeToNBT(tag);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, this.blockMetadata, tag);
+ }
+
+ @Override
+ public final void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
+ NBTTagCompound tag = pkt.func_148857_g();
+ readFromNBT(tag);
+ }
+
+ public int getBaseTickRate() {
+ return MathUtils.randInt(200, 300);
+ }
+
+ public abstract AutoMap<Class> aThingsToLookFor();
+
+ public abstract void onPreLogicTick();
+
+ public final void logicTick() {
+
+ if (this.worldObj == null || this.worldObj.isRemote) {
+ return;
+ }
+ if (internalTickCounter % getBaseTickRate() == 0) {
+ if (internalBlockLocation == null) {
+ internalBlockLocation = new BlockPos(this);
+ }
+ BlockPos p = internalBlockLocation;
+ if (p != null) {
+ if (p.world != null) {
+ World w = this.worldObj;
+ if (w == null) {
+ return;
+ }
+ Chunk c = w.getChunkFromBlockCoords(p.xPos, p.zPos);
+ if (c != null) {
+ if (c.isChunkLoaded) {
+ int startX = p.xPos - 2;
+ int startY = p.yPos;
+ int startZ = p.zPos - 2;
+ int endX = p.xPos + 3;
+ int endY = p.yPos + 5;
+ int endZ = p.zPos + 3;
+ AxisAlignedBB box = AxisAlignedBB.getBoundingBox(startX, startY, startZ, endX, endY, endZ);
+ if (box != null) {
+ for (Class c2 : aThingsToLookFor()) {
+ tickEntityType(w, box, c2);
+ }
+ } else {
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ internalTickCounter++;
+ }
+
+ @SuppressWarnings("unchecked")
+ public final void tickEntityType(World w, AxisAlignedBB box, Class aClassToFind) {
+ List<?> entities = w.getEntitiesWithinAABB(aClassToFind, box);
+ if (entities != null && !entities.isEmpty()) {
+ interactWithEntities(entities);
+ }
+ }
+
+ public final <V> void interactWithEntities(List<V> entities) {
+ for (V aEntity : entities) {
+ addDrop(aEntity);
+ if (this.tank.getFluidAmount() < this.tank.getCapacity()) {
+ int aFluidAmount = onPostTick(aEntity);
+ aFluidAmount = Math
+ .max(Math.min(this.tank.getCapacity() - this.tank.getFluidAmount(), aFluidAmount), 1);
+ this.tank.fill(FluidUtils.getFluidStack(fluidToProvide(), aFluidAmount), true);
+ } else {
+ ItemStack aDirtStack = ItemUtils.getSimpleStack(itemToSpawnInWorldIfTankIsFull(), 1);
+ if (!ItemUtils.checkForInvalidItems(aDirtStack)) {
+ return;
+ }
+ if (!this.mInventory.addItemStack(aDirtStack)) {
+ EntityItem entity = new EntityItem(worldObj, xCoord, yCoord + 1.5, zCoord, aDirtStack);
+ worldObj.spawnEntityInWorld(entity);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the amount of fluid for this entity type
+ *
+ * @param aEntity
+ * @return
+ */
+ public abstract <V> int onPostTick(V aEntity);
+
+ public abstract <V> boolean addDrop(V aPooMaker);
+
+ public abstract Fluid fluidToProvide();
+
+ public abstract ItemStack itemToSpawnInWorldIfTankIsFull();
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPestKiller.java b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPestKiller.java
new file mode 100644
index 0000000000..dfdb7104b0
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPestKiller.java
@@ -0,0 +1,532 @@
+package gtPlusPlus.core.tileentities.machines;
+
+import static gregtech.api.enums.Mods.Forestry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.passive.EntityBat;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ISidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.DamageSource;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidEvent;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTank;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+import net.minecraftforge.oredict.OreDictionary;
+
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.api.objects.minecraft.BTF_FluidTank;
+import gtPlusPlus.core.inventories.InventoryPestKiller;
+import gtPlusPlus.core.material.MISC_MATERIALS;
+import gtPlusPlus.core.recipe.common.CI;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.EntityUtils;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+import gtPlusPlus.core.util.reflect.ReflectionUtils;
+
+public class TileEntityPestKiller extends TileEntity implements ISidedInventory, IFluidHandler {
+
+ private final int mBaseTickRate = 20 * 30;
+ private final InventoryPestKiller mInventory;
+ private final FluidTank mTank;
+ private int mChunkX;
+ private int mChunkZ;
+ private boolean mSet = false;
+
+ private int mTickCounter = 0;
+ private int mUpdateTick = 0;
+ private boolean mNeedsUpdate = false;
+ private String mCustomName;
+
+ private static final AutoMap<Class<?>> mEntityMap = new AutoMap<>();
+
+ static {
+ mEntityMap.put(EntityBat.class);
+ if (Forestry.isModLoaded()) {
+ mEntityMap.put(ReflectionUtils.getClass("forestry.lepidopterology.entities.EntityButterfly"));
+ }
+ }
+
+ public TileEntityPestKiller() {
+ this.mInventory = new InventoryPestKiller();
+ mTank = new BTF_FluidTank(2000);
+ }
+
+ public InventoryPestKiller getInventory() {
+ return this.mInventory;
+ }
+
+ public FluidTank getTank() {
+ return mTank;
+ }
+
+ private void setup() {
+ World w = this.worldObj;
+ if (w != null) {
+ Chunk c = w.getChunkFromBlockCoords(this.xCoord, this.zCoord);
+ if (c != null) {
+ mChunkX = c.xPosition;
+ mChunkZ = c.zPosition;
+ mSet = true;
+ }
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public boolean tryKillPests() {
+ int min = 0;
+ int max = 0;
+ switch (getTier()) {
+ case 1 -> {
+ min = -2;
+ max = 3;
+ }
+ case 2 -> {
+ min = -4;
+ max = 5;
+ }
+ default -> {}
+ // code block
+ }
+ int aChunkCount = 0;
+ AutoMap<Entity> entities = new AutoMap<>();
+ if (min != 0 && max != 0) {
+ for (int x = min; x < max; x++) {
+ for (int z = min; z < max; z++) {
+ Chunk c = getChunkFromOffsetIfLoaded(x, z);
+ if (c != null) {
+ if (c.hasEntities) {
+ aChunkCount++;
+ List[] lists = c.entityLists;
+ for (List o : lists) {
+ for (Object e : o) {
+ if (e instanceof Entity) {
+ for (Class<?> C : mEntityMap) {
+ if (e.getClass()
+ .equals(C) || C.isAssignableFrom(e.getClass())) {
+ entities.put((Entity) e);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Chunk c = getChunkFromOffsetIfLoaded(0, 0);
+ if (c != null) {
+ if (c.hasEntities) {
+ List[] lists = c.entityLists;
+ for (List o : lists) {
+ for (Object e : o) {
+ if (e instanceof Entity) {
+ for (Class<?> C : mEntityMap) {
+ if (e.getClass()
+ .equals(C) || C.isAssignableFrom(e.getClass())) {
+ entities.put((Entity) e);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ boolean killed = false;
+ if (!entities.isEmpty()) {
+ for (Entity e : entities) {
+ if (e != null) {
+ if (e.isEntityAlive()) {
+ if (this.mTank.getFluidAmount() >= 1 || getTier() == 0) {
+ if (getTier() > 0) {
+ int aChanceToUse = MathUtils.randInt(1, (100 * getTier()));
+ if (aChanceToUse == 1) {
+ this.mTank.drain(1, true);
+ }
+ }
+ EntityUtils.doDamage(e, DamageSource.generic, Short.MAX_VALUE);
+ e.setDead();
+ killed = true;
+ }
+ }
+ }
+ }
+ }
+ updateTileEntity();
+ return killed;
+ }
+
+ public Chunk getChunkFromOffsetIfLoaded(int x, int y) {
+ Chunk c = this.worldObj.getChunkFromChunkCoords(mChunkX + x, mChunkZ + y);
+ if (c.isChunkLoaded) {
+ return c;
+ }
+ return null;
+ }
+
+ public int getTier() {
+ if (this.mTank != null) {
+ FluidStack f = mTank.getFluid();
+ if (f != null) {
+ if (f.isFluidEqual(FluidUtils.getWildcardFluidStack("formaldehyde", 1))) {
+ return 1;
+ } else if (f.isFluidEqual(MISC_MATERIALS.HYDROGEN_CYANIDE.getFluidStack(1))) {
+ return 2;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public void updateEntity() {
+ if (worldObj.isRemote) {
+ return;
+ }
+ if (!mSet) {
+ setup();
+ }
+ this.mTickCounter++;
+ if (this.mTank != null) {
+ if (this.hasFluidSpace()) {
+ handleInventory();
+ }
+ }
+ if (this.mTickCounter % this.mBaseTickRate == 0) {
+ tryKillPests();
+ }
+ updateTick();
+ }
+
+ public boolean anyPlayerInRange() {
+ return this.worldObj.getClosestPlayer(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D, 32) != null;
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ mTank.writeToNBT(nbt);
+ super.writeToNBT(nbt);
+ // Utils.LOG_MACHINE_INFO("Trying to write NBT data to TE.");
+ final NBTTagCompound chestData = new NBTTagCompound();
+ this.mInventory.writeToNBT(chestData);
+ nbt.setTag("ContentsChest", chestData);
+ if (this.hasCustomInventoryName()) {
+ nbt.setString("CustomName", this.getCustomName());
+ }
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ mTank.readFromNBT(nbt);
+ super.readFromNBT(nbt);
+ // Utils.LOG_MACHINE_INFO("Trying to read NBT data from TE.");
+ this.mInventory.readFromNBT(nbt.getCompoundTag("ContentsChest"));
+ if (nbt.hasKey("CustomName", 8)) {
+ this.setCustomName(nbt.getString("CustomName"));
+ }
+ }
+
+ @Override
+ public int getSizeInventory() {
+ return this.getInventory()
+ .getSizeInventory();
+ }
+
+ @Override
+ public ItemStack getStackInSlot(final int slot) {
+ return this.getInventory()
+ .getStackInSlot(slot);
+ }
+
+ @Override
+ public ItemStack decrStackSize(final int slot, final int count) {
+ return this.getInventory()
+ .decrStackSize(slot, count);
+ }
+
+ @Override
+ public ItemStack getStackInSlotOnClosing(final int slot) {
+ return this.getInventory()
+ .getStackInSlotOnClosing(slot);
+ }
+
+ @Override
+ public void setInventorySlotContents(final int slot, final ItemStack stack) {
+ this.getInventory()
+ .setInventorySlotContents(slot, stack);
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return this.getInventory()
+ .getInventoryStackLimit();
+ }
+
+ @Override
+ public boolean isUseableByPlayer(final EntityPlayer entityplayer) {
+ return this.getInventory()
+ .isUseableByPlayer(entityplayer);
+ }
+
+ @Override
+ public void openInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .openInventory();
+ }
+
+ @Override
+ public void closeInventory() {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType(), 1, 1);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType());
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord, this.getBlockType());
+ this.getInventory()
+ .closeInventory();
+ }
+
+ @Override
+ public boolean isItemValidForSlot(final int slot, final ItemStack itemstack) {
+ return this.getInventory()
+ .isItemValidForSlot(slot, itemstack);
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(final int p_94128_1_) {
+ final int[] accessibleSides = new int[this.getSizeInventory()];
+ for (int r = 0; r < this.getInventory()
+ .getSizeInventory(); r++) {
+ accessibleSides[r] = r;
+ }
+ return accessibleSides;
+ }
+
+ @Override
+ public boolean canInsertItem(final int aSlot, final ItemStack aStack, final int p_102007_3_) {
+ if (this.getInventory()
+ .getInventory()[0] == null) {
+ return true;
+ } else if (GT_Utility.areStacksEqual(
+ aStack,
+ this.getInventory()
+ .getInventory()[0])) {
+ if (this.getInventory()
+ .getInventory()[0].stackSize < 64) {
+ int diff = 64 - this.getInventory()
+ .getInventory()[0].stackSize;
+ if (aStack.stackSize <= diff) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canExtractItem(final int aSlot, final ItemStack aStack, final int p_102008_3_) {
+ if (this.getInventory()
+ .getInventory()[1] == null) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public String getCustomName() {
+ return this.mCustomName;
+ }
+
+ public void setCustomName(final String customName) {
+ this.mCustomName = customName;
+ }
+
+ @Override
+ public String getInventoryName() {
+ return this.hasCustomInventoryName() ? this.mCustomName : "container.pestkiller";
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return (this.mCustomName != null) && !this.mCustomName.equals("");
+ }
+
+ @Override
+ public final int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
+ updateTileEntity();
+ return this.mTank.fill(resource, doFill);
+ }
+
+ @Override
+ public final FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
+ updateTileEntity();
+ return this.mTank.drain(resource.amount, doDrain);
+ }
+
+ @Override
+ public final FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
+ FluidStack fluid = this.mTank.getFluid();
+ // return this.tank.drain(maxDrain, doDrain);
+ if (fluid == null) {
+ return null;
+ }
+
+ int drained = maxDrain;
+ if (fluid.amount < drained) {
+ drained = fluid.amount;
+ }
+
+ FluidStack stack = new FluidStack(fluid, drained);
+ if (doDrain) {
+ fluid.amount -= drained;
+ if (fluid.amount <= 0) {
+ fluid = null;
+ }
+
+ if (this != null) {
+ FluidEvent.fireEvent(
+ new FluidEvent.FluidDrainingEvent(
+ fluid,
+ this.getWorldObj(),
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ this.mTank,
+ 0));
+ }
+ }
+ updateTileEntity();
+ return stack;
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection from, Fluid fluid) {
+ return mTank.getFluid() == null || mTank.getFluid()
+ .getFluid()
+ .equals(fluid);
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection from, Fluid fluid) {
+ return false;
+ }
+
+ @Override
+ public final FluidTankInfo[] getTankInfo(ForgeDirection from) {
+ return new FluidTankInfo[] { this.mTank.getInfo() };
+ }
+
+ @Override
+ public final Packet getDescriptionPacket() {
+ NBTTagCompound tag = new NBTTagCompound();
+ writeToNBT(tag);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, this.blockMetadata, tag);
+ }
+
+ @Override
+ public final void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
+ NBTTagCompound tag = pkt.func_148857_g();
+ readFromNBT(tag);
+ }
+
+ public boolean hasFluidSpace() {
+ if (this.mTank.getFluidAmount() <= 1000) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean drainCell() {
+ boolean didFill = false;
+ ItemStack aInput = this.getStackInSlot(0);
+ if (aInput == null) {
+ return false;
+ }
+ aInput = aInput.copy();
+ if (aInput != null && (this.getStackInSlot(1) == null || this.getStackInSlot(1).stackSize < 64)) {
+ ArrayList<ItemStack> t1Cells = OreDictionary.getOres("cellFormaldehyde");
+ ArrayList<ItemStack> t2Cells = OreDictionary.getOres("cellHydrogenCyanide");
+ didFill = addFluid(t1Cells, aInput, FluidUtils.getWildcardFluidStack("formaldehyde", 1000));
+ if (!didFill) {
+ didFill = addFluid(t2Cells, aInput, MISC_MATERIALS.HYDROGEN_CYANIDE.getFluidStack(1000));
+ }
+ }
+
+ return didFill;
+ }
+
+ public boolean handleInventory() {
+ if (this.getInventory() != null && drainCell()) {
+ this.decrStackSize(0, 1);
+ if (this.getStackInSlot(1) == null) {
+ this.setInventorySlotContents(1, CI.emptyCells(1));
+ } else {
+ this.getStackInSlot(1).stackSize++;
+ }
+ this.updateTileEntity();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean addFluid(ArrayList<ItemStack> inputs, ItemStack aInput, FluidStack aFluidForInput) {
+ for (ItemStack a : inputs) {
+ if (GT_Utility.areStacksEqual(a, aInput)) {
+ if (mTank.getFluid() == null || mTank.getFluid()
+ .isFluidEqual(aFluidForInput)) {
+ boolean didFill = fill(ForgeDirection.UNKNOWN, aFluidForInput, true) > 0;
+ return didFill;
+ }
+ } else {
+ continue;
+ }
+ }
+ return false;
+ }
+
+ public void updateTileEntity() {
+ this.getInventory()
+ .markDirty();
+ this.markDirty();
+ this.mNeedsUpdate = true;
+ }
+
+ private void updateTick() {
+ if (mNeedsUpdate) {
+ if (mUpdateTick == 0) {
+ mUpdateTick = 4; // every 4 ticks it will send an update
+ } else {
+ --mUpdateTick;
+ if (mUpdateTick == 0) {
+ markDirty();
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ mNeedsUpdate = false;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPooCollector.java b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPooCollector.java
new file mode 100644
index 0000000000..d0d4ee3661
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityPooCollector.java
@@ -0,0 +1,128 @@
+package gtPlusPlus.core.tileentities.machines;
+
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.passive.EntityAnimal;
+import net.minecraft.entity.passive.EntityChicken;
+import net.minecraft.entity.passive.EntityCow;
+import net.minecraft.entity.passive.EntityHorse;
+import net.minecraft.entity.passive.EntityMooshroom;
+import net.minecraft.entity.passive.EntitySheep;
+import net.minecraft.entity.passive.IAnimals;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.item.chemistry.AgriculturalChem;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public class TileEntityPooCollector extends TileEntityBaseFluidCollector {
+
+ public TileEntityPooCollector() {
+ super(9, 8000);
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection from, Fluid fluid) {
+ return false;
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection from, Fluid fluid) {
+ return true;
+ }
+
+ @Override
+ public void onPreLogicTick() {}
+
+ @Override
+ public <V> boolean addDrop(V aPooMaker) {
+ int aChance = MathUtils.randInt(0, 50000);
+ if (aChance > 0) {
+ ItemStack aPoop;
+ if (aChance <= 100) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustManureByproducts", 1);
+ } else if (aChance <= 500) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustSmallManureByproducts", 1);
+ } else if (aChance <= 1250) {
+ aPoop = ItemUtils.getItemStackOfAmountFromOreDict("dustTinyManureByproducts", 1);
+ } else {
+ return false;
+ }
+ if (!ItemUtils.checkForInvalidItems(aPoop)) {
+ return false;
+ }
+
+ // Add poop to world
+ // Logger.INFO("Adding animal waste for "+aPooMaker.getCommandSenderName());
+
+ // Add to inventory if not full, else espawn in world
+ if (!this.mInventory.addItemStack(aPoop)) {
+ EntityItem entity = new EntityItem(worldObj, xCoord, yCoord + 1.5, zCoord, aPoop);
+ worldObj.spawnEntityInWorld(entity);
+ }
+ }
+
+ return false;
+ }
+
+ private static AutoMap<Class> aEntityToDrain = new AutoMap<>();
+
+ @Override
+ public AutoMap<Class> aThingsToLookFor() {
+ if (aEntityToDrain.isEmpty()) {
+ aEntityToDrain.add(EntityAnimal.class);
+ aEntityToDrain.add(IAnimals.class);
+ }
+ return aEntityToDrain;
+ }
+
+ @Override
+ public <V> int onPostTick(V aPooMaker) {
+ if (this.tank.getFluidAmount() < this.tank.getCapacity()) {
+ int aPooAmount = 0;
+ // Vanilla Animals
+ if (aPooMaker instanceof EntityChicken) {
+ aPooAmount = MathUtils.randInt(1, 40);
+ } else if (aPooMaker instanceof EntityHorse) {
+ aPooAmount = MathUtils.randInt(20, 40);
+ } else if (aPooMaker instanceof EntityCow) {
+ aPooAmount = MathUtils.randInt(18, 45);
+ } else if (aPooMaker instanceof EntityMooshroom) {
+ aPooAmount = 17;
+ } else if (aPooMaker instanceof EntitySheep) {
+ aPooAmount = MathUtils.randInt(8, 30);
+ } else {
+ if (aPooMaker instanceof EntityAnimal || aPooMaker instanceof IAnimals) {
+ aPooAmount = MathUtils.randInt(5, 35);
+ } else {
+ aPooAmount = MathUtils.randInt(1, 10);
+ }
+ }
+ aPooAmount = Math.max((Math.min(this.tank.getCapacity() - this.tank.getFluidAmount(), aPooAmount) / 10), 1);
+ return aPooAmount;
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public Fluid fluidToProvide() {
+ return AgriculturalChem.PoopJuice;
+ }
+
+ @Override
+ public ItemStack itemToSpawnInWorldIfTankIsFull() {
+ int a = MathUtils.randInt(0, 100);
+ ItemStack aItem = null;
+ if (a <= 30) {
+ aItem = ItemUtils.getSimpleStack(AgriculturalChem.dustDirt);
+ } else if (a <= 40) {
+ aItem = ItemUtils.getItemStackOfAmountFromOreDict("dustSmallManureByproducts", 1);
+ } else if (a <= 55) {
+ aItem = ItemUtils.getItemStackOfAmountFromOreDict("dustTinyManureByproducts", 1);
+ }
+ return aItem;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityProjectTable.java b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityProjectTable.java
new file mode 100644
index 0000000000..7c90ddc1c2
--- /dev/null
+++ b/src/main/java/gtPlusPlus/core/tileentities/machines/TileEntityProjectTable.java
@@ -0,0 +1,165 @@
+package gtPlusPlus.core.tileentities.machines;
+
+import java.util.List;
+import java.util.Vector;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+
+import gregtech.api.enums.ItemList;
+import gregtech.common.items.GT_MetaGenerated_Item_01;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.container.Container_ProjectTable;
+import gtPlusPlus.core.inventories.projecttable.InventoryProjectMain;
+import gtPlusPlus.core.inventories.projecttable.InventoryProjectOutput;
+import gtPlusPlus.core.util.minecraft.NBTUtils;
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
+import gtPlusPlus.xmod.gregtech.common.items.MetaGeneratedGregtechItems;
+import ic2.api.network.INetworkDataProvider;
+import ic2.api.network.INetworkUpdateListener;
+import ic2.api.tile.IWrenchable;
+import ic2.core.IC2;
+
+public class TileEntityProjectTable extends TileEntity
+ implements INetworkDataProvider, INetworkUpdateListener, IWrenchable {
+
+ public InventoryProjectMain inventoryGrid;
+ public InventoryProjectOutput inventoryOutputs;
+
+ private Container_ProjectTable container;
+
+ public TileEntityProjectTable() {
+ this.inventoryGrid = new InventoryProjectMain(); // number of slots - without product slot
+ this.inventoryOutputs = new InventoryProjectOutput(); // number of slots - without product slot
+ this.canUpdate();
+ }
+
+ public void setContainer(Container_ProjectTable container) {
+ this.container = container;
+ }
+
+ public NBTTagCompound getTag(final NBTTagCompound nbt, final String tag) {
+ if (!nbt.hasKey(tag)) {
+ nbt.setTag(tag, new NBTTagCompound());
+ }
+ return nbt.getCompoundTag(tag);
+ }
+
+ @Override
+ public void writeToNBT(final NBTTagCompound nbt) {
+ super.writeToNBT(nbt);
+ nbt.setShort("facing", this.facing);
+ this.inventoryGrid.writeToNBT(this.getTag(nbt, "ContentsGrid"));
+ this.inventoryOutputs.writeToNBT(this.getTag(nbt, "ContentsOutput"));
+ }
+
+ @Override
+ public void readFromNBT(final NBTTagCompound nbt) {
+ super.readFromNBT(nbt);
+ this.prevFacing = (this.facing = nbt.getShort("facing"));
+ this.inventoryGrid.readFromNBT(nbt.getCompoundTag("ContentsGrid"));
+ this.inventoryOutputs.readFromNBT(nbt.getCompoundTag("ContentsOutput"));
+ }
+
+ @Override
+ public List<String> getNetworkedFields() {
+ final List<String> ret = new Vector(2);
+ ret.add("facing");
+ return ret;
+ }
+
+ @Override
+ public boolean wrenchCanSetFacing(final EntityPlayer entityPlayer, final int side) {
+ return false;
+ }
+
+ private short facing = 0;
+ public short prevFacing = 0;
+
+ @Override
+ public void setFacing(final short facing1) {
+ this.facing = facing1;
+ if (this.prevFacing != facing1) {
+ IC2.network.get()
+ .updateTileEntityField(this, "facing");
+ }
+ this.prevFacing = facing1;
+ }
+
+ @Override
+ public short getFacing() {
+ return this.facing;
+ }
+
+ @Override
+ public boolean wrenchCanRemove(final EntityPlayer entityPlayer) {
+ return true;
+ }
+
+ @Override
+ public float getWrenchDropRate() {
+ return 1.0F;
+ }
+
+ @Override
+ public ItemStack getWrenchDrop(final EntityPlayer entityPlayer) {
+ return new ItemStack(
+ this.worldObj.getBlock(this.xCoord, this.yCoord, this.zCoord),
+ 1,
+ this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord));
+ }
+
+ @Override
+ public void onNetworkUpdate(final String field) {
+ this.prevFacing = this.facing;
+ }
+
+ @Override
+ public void updateEntity() {
+ if (!this.worldObj.isRemote) {
+ // Data stick
+ ItemStack dataStick = this.inventoryOutputs.getStackInSlot(0);
+ if (dataStick != null && this.container != null && container.getOutputContent() != null) {
+ if ((dataStick.getItem() instanceof GT_MetaGenerated_Item_01 && dataStick.getItemDamage() == 32708)
+ || (dataStick == ItemList.Tool_DataStick.get(1))
+ || (dataStick == GregtechItemList.Old_Tool_DataStick.get(1))
+ || (dataStick.getItem() instanceof MetaGeneratedGregtechItems
+ && dataStick.getItemDamage() == 32208)) {
+
+ Logger.INFO("Found Data Stick and valid container.");
+
+ ItemStack outputComponent = container.getOutputContent();
+ ItemStack[] craftInputComponent = container.getInputComponents();
+
+ ItemStack newStick = NBTUtils
+ .writeItemsToNBT(dataStick, new ItemStack[] { outputComponent }, "Output");
+ newStick = NBTUtils.writeItemsToNBT(newStick, craftInputComponent);
+ NBTUtils.setBookTitle(newStick, "Encrypted Project Data");
+ NBTUtils.setBoolean(newStick, "mEncrypted", true);
+ int slotm = 0;
+ Logger.WARNING("Uploading to Data Stick.");
+ for (ItemStack is : NBTUtils.readItemsFromNBT(newStick)) {
+ if (is != null) {
+ Logger.WARNING("Uploaded " + is.getDisplayName() + " into memory slot " + slotm + ".");
+ } else {
+ Logger.WARNING("Left memory slot " + slotm + " blank.");
+ }
+ slotm++;
+ }
+ Logger.WARNING("Encrypting Data Stick.");
+ this.inventoryOutputs.setInventorySlotContents(1, newStick);
+ this.inventoryOutputs.setInventorySlotContents(0, null);
+ }
+ }
+
+ }
+ super.updateEntity();
+ }
+
+ @Override
+ public boolean canUpdate() {
+ return true;
+ }
+}