aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/multitileentity/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api/multitileentity/base')
-rw-r--r--src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java1047
-rw-r--r--src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java55
-rw-r--r--src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java113
3 files changed, 1215 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java
new file mode 100644
index 0000000000..387b50d7c8
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java
@@ -0,0 +1,1047 @@
+package gregtech.api.multitileentity.base;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregtechWailaProvider;
+import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords;
+import gregtech.api.metatileentity.CoverableTileEntity;
+import gregtech.api.metatileentity.GregTechTileClientEvents;
+import gregtech.api.multitileentity.interfaces.IMultiTileEntity;
+import gregtech.api.multitileentity.MultiTileEntityBlockInternal;
+import gregtech.api.multitileentity.MultiTileEntityClassContainer;
+import gregtech.api.multitileentity.MultiTileEntityRegistry;
+import gregtech.api.net.GT_Packet_New;
+import gregtech.api.net.GT_Packet_TileEntity;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.render.IRenderedBlock;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.Packet;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.world.Explosion;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidTank;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+import static gregtech.api.enums.GT_Values.NBT;
+import static gregtech.api.enums.GT_Values.OPOS;
+import static gregtech.api.enums.GT_Values.SIDE_WEST;
+import static gregtech.api.enums.GT_Values.VALID_SIDES;
+
+public abstract class BaseMultiTileEntity extends CoverableTileEntity implements IMultiTileEntity, IHasWorldObjectAndCoords, IRenderedBlock, IGregtechWailaProvider {
+ // Makes a Bounding Box without having to constantly specify the Offset Coordinates.
+ protected static final float[] PX_BOX = {0, 0, 0, 1, 1, 1};
+
+ public Materials mMaterial = Materials._NULL;
+ protected final boolean mIsTicking; // If this TileEntity is ticking at all
+
+ protected boolean mShouldRefresh = true; // This Variable checks if this TileEntity should refresh when the Block is being set. That way you can turn this check off any time you need it.
+ protected boolean mDoesBlockUpdate = false; // This Variable is for a buffered Block Update.
+ protected boolean mForceFullSelectionBoxes = false; // This Variable is for forcing the Selection Box to be full.
+ protected boolean mNeedsUpdate = false;
+ protected boolean mInventoryChanged = false;
+ protected boolean mIsPainted = false;
+ protected byte mFacing = SIDE_WEST; // Default to WEST, so it renders facing Left in the inventory
+ protected byte mColor;
+ private short mMTEID = GT_Values.W, mMTERegistry = GT_Values.W;
+ private String mCustomName = null;
+ private String mOwnerName = "";
+ private UUID mOwnerUuid = GT_Utility.defaultUuid;
+ private boolean mLockUpgrade = false;
+
+ public BaseMultiTileEntity(boolean mIsTicking) {
+ this.mIsTicking = mIsTicking;
+ }
+
+ @Override
+ public short getMultiTileEntityID() {
+ return mMTEID;
+ }
+
+ @Override
+ public short getMultiTileEntityRegistryID() {
+ return mMTERegistry;
+ }
+
+ @Override
+ public void onRegistrationFirst(MultiTileEntityRegistry aRegistry, short aID) {
+ GameRegistry.registerTileEntity(getClass(), getTileEntityName());
+ }
+
+ @Override
+ public void initFromNBT(NBTTagCompound aNBT, short aMTEID, short aMTERegistry) {
+ // Set ID and Registry ID.
+ mMTEID = aMTEID;
+ mMTERegistry = aMTERegistry;
+ // Read the Default Parameters from NBT.
+ if (aNBT != null) readFromNBT(aNBT);
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound aNBT) {
+ // Check if this is a World/Chunk Loading Process calling readFromNBT.
+ if (mMTEID == GT_Values.W || mMTERegistry == GT_Values.W) {
+ // Yes it is, so read the ID Tags first.
+ mMTEID = aNBT.getShort(NBT.MTE_ID);
+ mMTERegistry = aNBT.getShort(NBT.MTE_REG);
+ // And add additional Default Parameters, in case the Mod updated with new ones.
+ final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mMTERegistry);
+ if (tRegistry != null) {
+ final MultiTileEntityClassContainer tClass = tRegistry.getClassContainer(mMTEID);
+ if (tClass != null) {
+ // Add the Default Parameters. Useful for things that differ between different tiers/types of the same machine
+ aNBT = GT_Util.fuseNBT(aNBT, tClass.mParameters);
+ }
+ }
+ }
+ // read the Coords if it has them.
+ if (aNBT.hasKey("x")) xCoord = aNBT.getInteger("x");
+ if (aNBT.hasKey("y")) yCoord = aNBT.getInteger("y");
+ if (aNBT.hasKey("z")) zCoord = aNBT.getInteger("z");
+ // read the custom Name.
+ if (aNBT.hasKey(NBT.DISPAY)) mCustomName = aNBT.getCompoundTag(NBT.DISPAY).getString(NBT.CUSTOM_NAME);
+
+ // And now everything else.
+ try {
+ if (aNBT.hasKey(NBT.MATERIAL)) mMaterial = Materials.get(aNBT.getString(NBT.MATERIAL));
+ mOwnerName = aNBT.getString(NBT.OWNER);
+ try {
+ mOwnerUuid = UUID.fromString(aNBT.getString(NBT.OWNER_UUID));
+ } catch (IllegalArgumentException e){
+ mOwnerUuid = null;
+ }
+ if (aNBT.hasKey(NBT.LOCK_UPGRADE)) mLockUpgrade = aNBT.getBoolean(NBT.LOCK_UPGRADE);
+ if (aNBT.hasKey(NBT.FACING)) mFacing = aNBT.getByte(NBT.FACING);
+
+ readCoverNBT(aNBT);
+ readMultiTileNBT(aNBT);
+
+ if (mCoverData == null || mCoverData.length != 6) mCoverData = new ISerializableObject[6];
+ if (mCoverSides.length != 6) mCoverSides = new int[]{0, 0, 0, 0, 0, 0};
+ if (mSidedRedstone.length != 6) mSidedRedstone = new byte[]{15, 15, 15, 15, 15, 15};
+
+ updateCoverBehavior();
+
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("readFromNBT", e);
+ }
+ }
+
+ public void readMultiTileNBT(NBTTagCompound aNBT) {
+ /* Do Nothing */
+ }
+
+ @Override
+ public final void writeToNBT(NBTTagCompound aNBT) {
+ super.writeToNBT(aNBT);
+ // write the IDs
+ aNBT.setShort(NBT.MTE_ID, mMTEID);
+ aNBT.setShort(NBT.MTE_REG, mMTERegistry);
+ // write the Custom Name
+ if (GT_Utility.isStringValid(mCustomName)) {
+ final NBTTagCompound displayNBT;
+ if (aNBT.hasKey(NBT.DISPAY)) {
+ displayNBT = aNBT.getCompoundTag(NBT.DISPAY);
+ } else {
+ displayNBT = new NBTTagCompound();
+ aNBT.setTag(NBT.DISPAY, displayNBT);
+ }
+ displayNBT.setString(NBT.CUSTOM_NAME, mCustomName);
+ }
+
+ // write the rest
+ try {
+ aNBT.setString(NBT.OWNER, mOwnerName);
+ aNBT.setString(NBT.OWNER_UUID, mOwnerUuid == null ? "" : mOwnerUuid.toString());
+ aNBT.setBoolean(NBT.LOCK_UPGRADE, mLockUpgrade);
+ aNBT.setByte(NBT.FACING, mFacing);
+
+ writeCoverNBT(aNBT, false);
+ writeMultiTileNBT(aNBT);
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("writeToNBT", e);
+ }
+ }
+
+ public void writeMultiTileNBT(NBTTagCompound aNBT) {
+ /* Do Nothing */
+ }
+
+ @Override
+ public NBTTagCompound writeItemNBT(NBTTagCompound aNBT) {
+ writeCoverNBT(aNBT, true);
+
+ return aNBT;
+ }
+
+
+ @Override
+ public long getTimer() {
+ return 0;
+ }
+
+ @Override
+ public int getRandomNumber(int aRange) {
+ return XSTR.XSTR_INSTANCE.nextInt(aRange);
+ }
+
+ @Override
+ public TileEntity getTileEntity(int aX, int aY, int aZ) {
+ if (worldObj == null || (ignoreUnloadedChunks && crossedChunkBorder(aX, aZ) && !worldObj.blockExists(aX, aY, aZ))) return null;
+ return GT_Util.getTileEntity(worldObj, aX, aY, aZ, true);
+ }
+
+ @Override
+ public boolean canUpdate() {
+ return mIsTicking && mShouldRefresh;
+ }
+
+ @Override
+ public boolean shouldRefresh(Block aOldBlock, Block aNewBlock, int aOldMeta, int aNewMeta, World aWorld, int aX, int aY, int aZ) {
+ return mShouldRefresh || aOldBlock != aNewBlock;
+ }
+
+ @Override
+ public void updateEntity() {
+ super.updateEntity();
+ if (mDoesBlockUpdate) doBlockUpdate();
+ }
+
+ public void doBlockUpdate() {
+ final Block tBlock = getBlock(getCoords());
+ worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, tBlock);
+ if (this instanceof IMTE_IsProvidingStrongPower) for (byte tSide : GT_Values.ALL_VALID_SIDES) {
+ if (getBlockAtSide(tSide).isNormalCube(worldObj, xCoord + GT_Values.OFFX[tSide], yCoord + GT_Values.OFFY[tSide], zCoord + GT_Values.OFFZ[tSide])) {
+ worldObj.notifyBlocksOfNeighborChange(
+ xCoord + GT_Values.OFFX[tSide], yCoord + GT_Values.OFFY[tSide], zCoord + GT_Values.OFFZ[tSide], tBlock, OPOS[tSide]
+ );
+ }
+ }
+ mDoesBlockUpdate = false;
+ }
+
+ @Override
+ public boolean shouldSideBeRendered(byte aSide) {
+ final TileEntity tTileEntity = getTileEntityAtSideAndDistance(aSide, 1);
+ // TODO: check to an interface
+ // if (getBlockAtSide(aSide) == Blocks.glass) return false;
+ return tTileEntity instanceof IMultiTileEntity ? !((IMultiTileEntity) tTileEntity).isSurfaceOpaque(OPOS[aSide]) : !getBlockAtSide(aSide).isOpaqueCube();
+ }
+
+ @Override
+ public boolean isSurfaceOpaque(byte aSide) {
+ return true;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public final IRenderedBlock passRenderingToObject(ItemStack aStack) {
+ return this;
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public final IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) {
+ return this;
+ }
+
+ @Override public int getRenderPasses(Block aBlock) {return 1;}
+ @Override public boolean usesRenderPass(int aRenderPass) {return true;}
+ @Override public boolean setBlockBounds(Block aBlock, int aRenderPass) {return false;}
+ @Override public boolean renderItem(Block aBlock, RenderBlocks aRenderer) {return false;}
+ @Override public boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) {return false;}
+
+ @Override
+ public ITexture[] getTexture(Block aBlock, byte aSide) {
+ return getTexture(aBlock, aSide, 1, VALID_SIDES);
+ }
+
+ @Override public final ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) {
+ if (!aShouldSideBeRendered[aSide]) return null;
+
+ final ITexture coverTexture = getCoverTexture(aSide);
+ final ITexture[] textureUncovered = getTexture(aBlock, aSide, true, aRenderPass);
+
+ if (coverTexture != null) {
+ final ITexture[] textureCovered = Arrays.copyOf(textureUncovered, textureUncovered.length + 1);
+ textureCovered[textureUncovered.length] = coverTexture;
+ return textureCovered;
+ } else {
+ return textureUncovered;
+ }
+ }
+
+ @Override
+ public void setCustomName(String aName) {
+ mCustomName = aName;
+ }
+
+ @Override
+ public String getCustomName() {
+ return GT_Utility.isStringValid(mCustomName) ? mCustomName : null;
+ }
+
+ @Override
+ public byte getColorization() {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public boolean unpaint() {
+ return false;
+ }
+
+ @Override
+ public byte setColorization(byte aColor) {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public boolean isPainted() {
+ return false;
+ }
+
+ @Override
+ public boolean paint(int aRGB) {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(byte aFacing) {
+ return false;
+ }
+
+ @Override
+ public byte getFrontFacing() {
+ return mFacing;
+ }
+
+ /**
+ * Sets the main facing to {aSide} and update as appropriately
+ * @return Whether the facing was changed
+ */
+ @Override
+ public boolean setMainFacing(byte aSide) {
+ if(!isValidFacing(aSide)) return false;
+ mFacing = aSide;
+
+ issueClientUpdate();
+ issueBlockUpdate();
+ onFacingChange();
+ checkDropCover();
+ doEnetUpdate();
+
+ if (shouldTriggerBlockUpdate()) {
+ // If we're triggering a block update this will call onMachineBlockUpdate()
+ GregTech_API.causeMachineUpdate(worldObj, xCoord, yCoord, zCoord);
+ } else {
+ // If we're not trigger a cascading one, call the update here.
+ onMachineBlockUpdate();
+ }
+ return true;
+ }
+
+ @Override
+ public int getPaint() {
+ return GT_Values.UNCOLORED;
+ }
+
+ @Override
+ public byte getBackFacing() {
+ return GT_Utility.getOppositeSide(mFacing);
+ }
+
+ @Override
+ public boolean isValidFacing(byte aSide) {
+ return aSide >= 0 && aSide <= 6 && getValidFacings()[aSide];
+ }
+
+ @Override
+ public boolean[] getValidFacings() {
+ return VALID_SIDES;
+ }
+
+ @Override
+ public void issueCoverUpdate(byte aSide) {
+ super.issueCoverUpdate(aSide);
+ issueClientUpdate();
+ }
+
+ public AxisAlignedBB box(double[] aBox) {
+ return AxisAlignedBB.getBoundingBox(
+ xCoord + aBox[0], yCoord + aBox[1], zCoord + aBox[2], xCoord + aBox[3], yCoord + aBox[4], zCoord + aBox[5]
+ );
+ }
+
+ public boolean box(AxisAlignedBB aAABB, List<AxisAlignedBB> aList, double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, double aMaxZ) {
+ final AxisAlignedBB tBox = box(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
+ return tBox.intersectsWith(aAABB) && aList.add(tBox);
+ }
+
+ @Override
+ public void onFacingChange() {/*Do nothing*/}
+
+ public AxisAlignedBB box(double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, double aMaxZ) {
+ return AxisAlignedBB.getBoundingBox(xCoord + aMinX, yCoord + aMinY, zCoord + aMinZ, xCoord + aMaxX, yCoord + aMaxY, zCoord + aMaxZ);
+ }
+
+ @Override
+ public boolean shouldTriggerBlockUpdate() {
+ return false;
+ }
+
+ public boolean box(AxisAlignedBB aAABB, List<AxisAlignedBB> aList, double[] aBox) {
+ final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]);
+ return tBox.intersectsWith(aAABB) && aList.add(tBox);
+ }
+
+ @Override
+ public void onMachineBlockUpdate() {/*Do nothing*/}
+
+ public boolean box(AxisAlignedBB aAABB, List<AxisAlignedBB> aList, float[] aBox) {
+ final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]);
+ return tBox.intersectsWith(aAABB) && aList.add(tBox);
+ }
+
+ public boolean box(AxisAlignedBB aAABB, List<AxisAlignedBB> aList) {
+ final AxisAlignedBB tBox = box(PX_BOX);
+ return tBox.intersectsWith(aAABB) && aList.add(tBox);
+ }
+
+ public AxisAlignedBB box(float[] aBox) {
+ return AxisAlignedBB.getBoundingBox(xCoord + aBox[0], yCoord + aBox[1], zCoord + aBox[2], xCoord + aBox[3], yCoord + aBox[4], zCoord + aBox[5]);
+ }
+
+ public boolean box(Block aBlock) {
+ aBlock.setBlockBounds(0, 0, 0, 1, 1, 1);
+ return true;
+ }
+
+ /**
+ * Causes a general Texture update.
+ * <p/>
+ * Only used Client Side to mark Blocks dirty.
+ */
+ @Override
+ public void issueTextureUpdate() {
+ if (!mIsTicking) {
+ markBlockForUpdate();
+ } else {
+ mNeedsUpdate = true;
+ }
+ }
+
+ public boolean box(Block aBlock, double[] aBox) {
+ aBlock.setBlockBounds((float) aBox[0], (float) aBox[1], (float) aBox[2], (float) aBox[3], (float) aBox[4], (float) aBox[5]);
+ return true;
+ }
+
+
+ protected void markBlockForUpdate() {
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ //worldObj.func_147479_m(xCoord, yCoord, zCoord);
+ mNeedsUpdate = false;
+
+ }
+
+ public boolean box(Block aBlock, float[] aBox) {
+ aBlock.setBlockBounds(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]);
+ return true;
+ }
+
+ @Override
+ public void onTileEntityPlaced() {
+ /* empty */
+ }
+
+ public boolean box(Block aBlock, double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, double aMaxZ) {
+ aBlock.setBlockBounds((float) aMinX, (float) aMinY, (float) aMinZ, (float) aMaxX, (float) aMaxY, (float) aMaxZ);
+ return true;
+ }
+
+ @Override
+ public void setShouldRefresh(boolean aShouldRefresh) {
+ mShouldRefresh = aShouldRefresh;
+ }
+
+ /**
+ * shouldJoinIc2Enet - defaults to false, override to change
+ */
+ @Override
+ public boolean shouldJoinIc2Enet() {
+ return false;
+ }
+
+ @Override
+ public final void addCollisionBoxesToList(AxisAlignedBB aAABB, List<AxisAlignedBB> aList, Entity aEntity) {
+ box(getCollisionBoundingBoxFromPool(), aAABB, aList);
+ }
+
+ /**
+ * Simple Function to prevent Block Updates from happening multiple times within the same Tick.
+ */
+ @Override
+ public final void issueBlockUpdate() {
+ if (mIsTicking) mDoesBlockUpdate = true;
+ else doBlockUpdate();
+ }
+
+ @Override
+ public boolean isStillValid() {
+ return !isInvalid();
+ }
+
+ @Override
+ public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) {
+ return true;
+ }
+
+ public AxisAlignedBB box() {
+ return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 1, zCoord + 1);
+ }
+
+ public boolean box(AxisAlignedBB aBox, AxisAlignedBB aAABB, List<AxisAlignedBB> aList) {
+ return aBox != null && aBox.intersectsWith(aAABB) && aList.add(aBox);
+ }
+
+ public float[] shrunkBox() {
+ return PX_BOX;
+ }
+
+ @Override
+ public void setBlockBoundsBasedOnState(Block aBlock) {
+ box(aBlock);
+ }
+
+ @Override
+ public AxisAlignedBB getCollisionBoundingBoxFromPool() {
+ return box();
+ }
+
+ @Override
+ public AxisAlignedBB getSelectedBoundingBoxFromPool() {
+ if (mForceFullSelectionBoxes) return box();
+ return box(shrunkBox());
+ }
+
+ @Override
+ public ItemStack getPickBlock(MovingObjectPosition aTarget) {
+ final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mMTERegistry);
+ return tRegistry == null ? null : tRegistry.getItem(mMTEID, writeItemNBT(new NBTTagCompound()));
+ }
+
+ @Override
+ public void onBlockAdded() {
+
+ }
+
+ @Override
+ public String getOwnerName() {
+ if (GT_Utility.isStringInvalid(mOwnerName)) return "Player";
+ return mOwnerName;
+ }
+
+ @Override
+ public String setOwnerName(String aName) {
+ if (GT_Utility.isStringInvalid(aName)) return mOwnerName = "Player";
+ return mOwnerName = aName;
+ }
+
+ @Override
+ public UUID getOwnerUuid() {
+ return mOwnerUuid;
+ }
+
+ @Override
+ public void setOwnerUuid(UUID uuid) {
+ mOwnerUuid = uuid;
+ }
+
+ @Override
+ public boolean onPlaced(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, byte aSide, float aHitX, float aHitY, float aHitZ) {
+ mFacing = getSideForPlayerPlacing(aPlayer, mFacing, getValidFacings());
+ onFacingChange();
+ return true;
+ }
+
+ @Override
+ public boolean allowInteraction(Entity aEntity) {
+ return true;
+ }
+
+ public boolean allowRightclick(Entity aEntity) {
+ return allowInteraction(aEntity);
+ }
+
+ @Override
+ public boolean onBlockActivated(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) {
+ try {
+ return allowRightclick(aPlayer) && onRightClick(aPlayer, aSide, aX, aY, aZ);
+ } catch(Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ return true;
+ }
+ }
+ @Override
+ public boolean onRightClick(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) {
+ if (isClientSide()) {
+ //Configure Cover, sneak can also be: screwdriver, wrench, side cutter, soldering iron
+ if (aPlayer.isSneaking()) {
+ final byte tSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) : aSide;
+ return (getCoverBehaviorAtSideNew(tSide).hasCoverGUI());
+ } else if (getCoverBehaviorAtSideNew(aSide).onCoverRightclickClient(aSide, this, aPlayer, aX, aY, aZ)) {
+ return true;
+ }
+
+ if (!getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this))
+ return false;
+ }
+ if (isServerSide()) {
+ if (!privateAccess() || aPlayer.getDisplayName().equalsIgnoreCase(getOwnerName())) {
+ final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ final byte wrenchSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ);
+
+ if(tCurrentItem != null) {
+ if (getColorization() >= 0 && GT_Utility.areStacksEqual(new ItemStack(Items.water_bucket, 1), tCurrentItem)) {
+ // TODO (Colorization)
+ }
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) return onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) return onScrewdriverRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)) return onHammerRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) return onMalletRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) return onSolderingRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)) return onWireCutterRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ);
+
+ final byte coverSide = getCoverIDAtSide(aSide) == 0 ? wrenchSide : aSide;
+
+ if (getCoverIDAtSide(coverSide) == 0) {
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) {
+ if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, tCurrentItem, this) &&
+ allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem)))
+ {
+ setCoverItemAtSide(coverSide, tCurrentItem);
+ if (!aPlayer.capabilities.isCreativeMode) tCurrentItem.stackSize--;
+ GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord);
+ issueClientUpdate();
+ }
+ sendCoverDataIfNeeded();
+ return true;
+ }
+ } else {
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCrowbarList)) {
+ if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) {
+ GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(0), 1.0F, -1, xCoord, yCoord, zCoord);
+ dropCover(coverSide, aSide, false);
+ }
+ sendCoverDataIfNeeded();
+ return true;
+ }
+ }
+ } else if (aPlayer.isSneaking()) { //Sneak click, no tool -> open cover config if possible.
+ aSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) : aSide;
+ return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSideNew(aSide).onCoverShiftRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer);
+ }
+
+ if (getCoverBehaviorAtSideNew(aSide).onCoverRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ))
+ return true;
+
+ if (!getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this))
+ return false;
+
+
+ }
+ }
+ return false;
+ }
+
+ public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+ if(setMainFacing(wrenchSide)) {
+ GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer);
+ GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord);
+ }
+ return true;
+ }
+
+ public boolean onScrewdriverRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+ if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) {
+ setCoverDataAtSide(wrenchSide, getCoverBehaviorAtSideNew(wrenchSide).onCoverScrewdriverClick(wrenchSide, getCoverIDAtSide(wrenchSide), getComplexCoverDataAtSide(wrenchSide), this, aPlayer, aX, aY, aZ));
+ // TODO: Update connections!
+ GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord);
+ }
+ return true;
+ }
+
+ public boolean onHammerRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+
+ return true;
+ }
+
+ public boolean onMalletRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+
+ return true;
+ }
+
+ public boolean onSolderingRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+
+ return true;
+ }
+
+ public boolean onWireCutterRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, float aZ) {
+
+ return true;
+ }
+
+ @Override
+ public float getExplosionResistance(Entity aExploder, double aExplosionX, double aExplosionY, double aExplosionZ) {
+ return getExplosionResistance();
+ }
+
+ @Override
+ public float getExplosionResistance() {
+ return 10.0F;
+ }
+
+ @Override
+ public void onExploded(Explosion aExplosion) {
+
+ }
+
+ @Override
+ public boolean isSideSolid(byte aSide) {
+ return true;
+ }
+
+ @Override
+ public ArrayList<ItemStack> getDrops(int aFortune, boolean aSilkTouch) {
+ final ArrayList<ItemStack> rList = new ArrayList<>();
+ final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID());
+ if (tRegistry != null) rList.add(tRegistry.getItem(getMultiTileEntityID(), writeItemNBT(new NBTTagCompound())));
+ return rList;
+ }
+
+
+ @Override
+ public boolean getSubItems(MultiTileEntityBlockInternal aBlock, Item aItem, CreativeTabs aTab, List<ItemStack> aList, short aID) {
+ return true;
+ }
+
+
+ @Override
+ public boolean recolourBlock(byte aSide, byte aColor) {
+// if (aColor > 15 || aColor < -1) aColor = -1;
+// if(paint((byte) (aColor + 1))) {
+//// updateClientData();
+//// causeBlockUpdate();
+// return true;
+// }
+// if (unpaint()) {updateClientData(); causeBlockUpdate(); return T;}
+// mColor = (byte) (aColor + 1);
+//// if (canAccessData()) mMetaTileEntity.onColorChangeServer(aColor);
+ return false;
+ }
+
+
+ @Override
+ public boolean playerOwnsThis(EntityPlayer aPlayer, boolean aCheckPrecicely) {
+ if (aCheckPrecicely || privateAccess() || (mOwnerName.length() == 0))
+ if ((mOwnerName.length() == 0) && isServerSide()) {
+ setOwnerName(aPlayer.getDisplayName());
+ setOwnerUuid(aPlayer.getUniqueID());
+ } else
+ return !privateAccess() || aPlayer.getDisplayName().equals("Player") || mOwnerName.equals("Player") || mOwnerName.equals(
+ aPlayer.getDisplayName());
+ return true;
+ }
+
+ @Override
+ public boolean privateAccess() {
+ return mLockUpgrade;
+ }
+
+ public byte getTextureData() {
+ return 0;
+ }
+
+ /**
+ * @return a Packet containing all Data which has to be synchronised to the Client - Override as needed
+ */
+ public GT_Packet_New getClientDataPacket() {
+ return new GT_Packet_TileEntity(
+ xCoord, (short) yCoord, zCoord,
+ getMultiTileEntityRegistryID(), getMultiTileEntityID(),
+ mCoverSides[0], mCoverSides[1], mCoverSides[2], mCoverSides[3], mCoverSides[4], mCoverSides[5],
+ (byte) ((mFacing & 7) | (mRedstone ? 16 : 0)),
+ (byte) getTextureData(), /*getTexturePage()*/
+ (byte) 0, /*getUpdateData()*/
+ (byte) (((mSidedRedstone[0] > 0) ? 1 : 0) | ((mSidedRedstone[1] > 0) ? 2 : 0) | ((mSidedRedstone[2] > 0) ? 4 : 0) | ((mSidedRedstone[3] > 0) ? 8 : 0) | ((mSidedRedstone[4] > 0) ? 16 : 0) | ((mSidedRedstone[5] > 0) ? 32 : 0)),
+ mColor
+ );
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ issueClientUpdate();
+ return null;
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currenttip, IWailaDataAccessor accessor, IWailaConfigHandler config) {
+ super.getWailaBody(itemStack, currenttip, accessor, config);
+ currenttip.add(String.format("Facing: %s", ForgeDirection.getOrientation(getFrontFacing()).name()));
+ }
+
+ @Override
+ public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, int z) {
+ super.getWailaNBTData(player, tile, tag, world, x, y, z);
+ }
+
+
+ @Override
+ public void sendClientData( EntityPlayerMP aPlayer) {
+ if(worldObj == null || worldObj.isRemote) return;
+ final GT_Packet_New tPacket = getClientDataPacket();
+ if(aPlayer == null) {
+ GT_Values.NW.sendPacketToAllPlayersInRange(worldObj, tPacket, getXCoord(), getZCoord());
+ } else {
+ GT_Values.NW.sendToPlayer(tPacket, aPlayer);
+ }
+ sendCoverDataIfNeeded();
+ }
+ public void setTextureData(byte aValue) {/*Do nothing*/}
+
+ @Override
+ public boolean receiveClientEvent(int aEventID, int aValue) {
+ super.receiveClientEvent(aEventID, aValue);
+ if (isClientSide()) {
+ issueTextureUpdate();
+ switch (aEventID) {
+ case GregTechTileClientEvents.CHANGE_COMMON_DATA:
+ mFacing = (byte) (aValue & 7);
+ //mActive = ((aValue & 8) != 0);
+ mRedstone = ((aValue & 16) != 0);
+ //mLockUpgrade = ((aValue&32) != 0);
+ //mWorks = ((aValue & 64) != 0);
+ break;
+ case GregTechTileClientEvents.CHANGE_CUSTOM_DATA:
+ if ((aValue & 0x80) != 0) // Is texture index
+ setTextureData((byte) (aValue & 0x7F));
+ //else if (mMetaTileEntity instanceof GT_MetaTileEntity_Hatch)//is texture page and hatch
+ // ((GT_MetaTileEntity_Hatch) mMetaTileEntity).onTexturePageUpdate((byte) (aValue & 0x7F));
+ break;
+ case GregTechTileClientEvents.CHANGE_COLOR:
+ if (aValue > 16 || aValue < 0) aValue = 0;
+ mColor = (byte) aValue;
+ break;
+ case GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT:
+ mSidedRedstone[0] = (byte) ((aValue & 1) == 1 ? 15 : 0);
+ mSidedRedstone[1] = (byte) ((aValue & 2) == 2 ? 15 : 0);
+ mSidedRedstone[2] = (byte) ((aValue & 4) == 4 ? 15 : 0);
+ mSidedRedstone[3] = (byte) ((aValue & 8) == 8 ? 15 : 0);
+ mSidedRedstone[4] = (byte) ((aValue & 16) == 16 ? 15 : 0);
+ mSidedRedstone[5] = (byte) ((aValue & 32) == 32 ? 15 : 0);
+ break;
+// case GregTechTileClientEvents.DO_SOUND:
+// if (mTickTimer > 20)
+// doSound((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
+// break;
+// case GregTechTileClientEvents.START_SOUND_LOOP:
+// if (mTickTimer > 20)
+// startSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
+// break;
+// case GregTechTileClientEvents.STOP_SOUND_LOOP:
+// if (mTickTimer > 20)
+// stopSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
+// break;
+// case GregTechTileClientEvents.CHANGE_LIGHT:
+// mLightValue = (byte) aValue;
+// break;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean hasCustomInventoryName() {
+ return false;
+ }
+
+ @Override
+ public ArrayList<String> getDebugInfo(EntityPlayer aPlayer, int aLogLevel) {
+ final ArrayList<String> tList = new ArrayList<>();
+ if (aLogLevel > 2) {
+ tList.add("MultiTileRegistry-ID: " + EnumChatFormatting.BLUE + mMTERegistry + EnumChatFormatting.RESET + " MultiTile-ID: " + EnumChatFormatting.BLUE + mMTEID + EnumChatFormatting.RESET);
+ }
+ if(joinedIc2Enet)
+ tList.add("Joined IC2 ENet");
+
+ addDebugInfo(aPlayer, aLogLevel, tList);
+
+ return tList;
+ }
+
+ protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList<String> tList) {
+ /* Do nothing */
+ }
+
+ /**
+ * Fluid - A Default implementation of the Fluid Tank behaviour, so that every TileEntity can use this to simplify its Code.
+ */
+ protected IFluidTank getFluidTankFillable(byte aSide, FluidStack aFluidToFill) {return null;}
+ protected IFluidTank getFluidTankDrainable(byte aSide, FluidStack aFluidToDrain) {return null;}
+ protected IFluidTank[] getFluidTanks(byte aSide) { return GT_Values.emptyFluidTank; }
+
+ public boolean isLiquidInput(byte aSide) {return true;}
+
+ public boolean isLiquidOutput(byte aSide) {return true;}
+
+ @Override
+ public int fill(ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) {
+ if (aFluid == null || aFluid.amount <= 0) return 0;
+ final IFluidTank tTank = getFluidTankFillable((byte)aDirection.ordinal(), aFluid);
+ return (tTank == null) ? 0 : tTank.fill(aFluid, aDoFill);
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) {
+ if (aFluid == null || aFluid.amount <= 0) return null;
+ final IFluidTank tTank = getFluidTankDrainable((byte)aDirection.ordinal(), aFluid);
+ if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0 || !tTank.getFluid().isFluidEqual(aFluid)) return null;
+ return tTank.drain(aFluid.amount, aDoDrain);
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) {
+ if (aAmountToDrain <= 0) return null;
+ final IFluidTank tTank = getFluidTankDrainable((byte)aDirection.ordinal(), null);
+ if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null;
+ return tTank.drain(aAmountToDrain, aDoDrain);
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection aDirection, Fluid aFluid) {
+ if (aFluid == null) return false;
+ final IFluidTank tTank = getFluidTankFillable((byte)aDirection.ordinal(), new FluidStack(aFluid, 0));
+ return tTank != null && (tTank.getFluid() == null || tTank.getFluid().getFluid() == aFluid);
+ }
+
+ @Override
+ public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) {
+ if (aFluid == null) return false;
+ final IFluidTank tTank = getFluidTankDrainable((byte)aDirection.ordinal(), new FluidStack(aFluid, 0));
+ return tTank != null && (tTank.getFluid() != null && tTank.getFluid().getFluid() == aFluid);
+ }
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) {
+ final IFluidTank[] tTanks = getFluidTanks((byte)aDirection.ordinal());
+ if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo;
+ final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length];
+ for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]);
+ return rInfo;
+ }
+
+ /**
+ * Energy - Do nothing by Default
+ */
+ @Override public boolean isUniversalEnergyStored(long aEnergyAmount) { return false; }
+ @Override public long getUniversalEnergyStored() { return 0; }
+ @Override public long getUniversalEnergyCapacity() { return 0; }
+ @Override public long getOutputAmperage() { return 0; }
+ @Override public long getOutputVoltage() { return 0; }
+ @Override public long getInputAmperage() { return 0; }
+ @Override public long getInputVoltage() { return 0; }
+ @Override public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLessEnergy) { return false; }
+ @Override public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) { return false; }
+ @Override public boolean drainEnergyUnits(byte aSide, long aVoltage, long aAmperage) { return false; }
+ @Override public long getAverageElectricInput() { return 0; }
+ @Override public long getAverageElectricOutput() { return 0; }
+ @Override public long getStoredEU() { return 0; }
+ @Override public long getEUCapacity() { return 0; }
+ @Override public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { return 0; }
+ @Override public boolean inputEnergyFrom(byte aSide) { return false; }
+ @Override public boolean outputsEnergyTo(byte aSide) { return false; }
+
+ /**
+ * Inventory - Do nothing by default
+ */
+ @Override public void openInventory() { /* Do nothing */ }
+ @Override public void closeInventory() { /* Do nothing */ }
+ @Override public boolean hasInventoryBeenModified() { return false; }
+ @Override public boolean isValidSlot(int aIndex) { return false; }
+ @Override public boolean addStackToSlot(int aIndex, ItemStack aStack) { return false; }
+ @Override public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) { return false; }
+ @Override public int[] getAccessibleSlotsFromSide(int aSide) { return GT_Values.emptyIntArray; }
+ @Override public boolean canInsertItem(int aSlot, ItemStack aStack, int aSide) { return false; }
+ @Override public boolean canExtractItem(int aSlot, ItemStack aStack, int aSide) { return false; }
+ @Override public int getSizeInventory() { return 0; }
+ @Override public ItemStack getStackInSlot(int aSlot) { return null; }
+ @Override public ItemStack decrStackSize(int aSlot, int aDecrement) { return null; }
+ @Override public ItemStack getStackInSlotOnClosing(int aSlot) { return null; }
+ @Override public void setInventorySlotContents(int aSlot, ItemStack aStack) { /* Do nothing */ }
+ @Override public int getInventoryStackLimit() { return 0; }
+ @Override public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { return false; }
+ @Override public void markInventoryBeenModified() { mInventoryChanged = true; }
+
+
+ /*
+ * Cover Helpers
+ */
+
+ public boolean coverLetsFluidIn(byte aSide, Fluid aFluid) {
+ return getCoverBehaviorAtSideNew(aSide).letsFluidIn(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), aFluid, this);
+ }
+ public boolean coverLetsFluidOut(byte aSide, Fluid aFluid) {
+ return getCoverBehaviorAtSideNew(aSide).letsFluidOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), aFluid, this);
+ }
+
+ public boolean coverLetsEnergyIn(byte aSide) {
+ return getCoverBehaviorAtSideNew(aSide).letsEnergyIn(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this);
+ }
+ public boolean coverLetsEnergyOut(byte aSide) {
+ return getCoverBehaviorAtSideNew(aSide).letsEnergyOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this);
+ }
+
+ public boolean coverLetsItemsIn(byte aSide, int aSlot) {
+ return getCoverBehaviorAtSideNew(aSide).letsItemsIn(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), aSlot, this);
+ }
+ public boolean coverLetsItemsOut(byte aSide, int aSlot) {
+ return getCoverBehaviorAtSideNew(aSide).letsItemsOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), aSlot,this);
+ }
+
+}
diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java
new file mode 100644
index 0000000000..2e689a6bae
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java
@@ -0,0 +1,55 @@
+package gregtech.api.multitileentity.base;
+import gregtech.api.net.GT_Packet_SendCoverData;
+import gregtech.api.util.ISerializableObject;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.Packet;
+
+import static gregtech.api.enums.GT_Values.NW;
+
+public abstract class BaseNontickableMultiTileEntity extends BaseMultiTileEntity {
+ boolean mConstructed = false; // Keeps track of whether this TE has been constructed and placed in the world
+ public BaseNontickableMultiTileEntity() {
+ super(false);
+ }
+
+ @Override
+ public void issueClientUpdate() {
+ if(worldObj != null && !worldObj.isRemote) sendClientData(null);
+ }
+
+ @Override
+ public Packet getDescriptionPacket() {
+ // We should have a world object and have been constructed by this point
+ mConstructed = true;
+
+ super.getDescriptionPacket();
+ // We don't get ticked, so if we have any cover data that needs to be sent, send it now
+ sendCoverDataIfNeeded();
+ return null;
+ }
+
+ @Override
+ public void issueCoverUpdate(byte aSide) {
+ if(!mConstructed) {
+ // Queue these up and send them with the description packet
+ super.issueCoverUpdate(aSide);
+ } else {
+ // Otherwise, send the data right away
+ NW.sendPacketToAllPlayersInRange(
+ worldObj,
+ new GT_Packet_SendCoverData(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this),
+ xCoord, zCoord
+ );
+ // Just in case
+ mCoverNeedUpdate[aSide] = false;
+ }
+ }
+
+ @Override
+ public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, EntityPlayerMP aPlayer) {
+ super.receiveCoverData(aCoverSide, aCoverID, aCoverData, aPlayer);
+ // We don't get ticked so issue the texture update right away
+ issueTextureUpdate();
+ }
+
+}
diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java
new file mode 100644
index 0000000000..c8bc04557f
--- /dev/null
+++ b/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java
@@ -0,0 +1,113 @@
+package gregtech.api.multitileentity.base;
+
+import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_OnNeighborBlockChange;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Util;
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.world.World;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+
+public abstract class BaseTickableMultiTileEntity extends BaseMultiTileEntity implements IMTE_OnNeighborBlockChange {
+ /** Variable for seeing if the Tick Function is called right now. */
+ public boolean mIsRunningTick = false;
+ /** Gets set to true when the Block received a Block Update. */
+ public boolean mBlockUpdated = false;
+ /** Timer Value */
+ protected long mTimer = 0;
+ /** Variable for updating Data to the Client */
+ private boolean mSendClientData = false;
+
+
+ public BaseTickableMultiTileEntity() {
+ super(true);
+ }
+
+ @Override
+ public final void updateEntity() {
+ mIsRunningTick = true;
+ final boolean isServerSide = isServerSide();
+ try {
+ if (mTimer++ == 0) {
+ markDirty();
+ GT_Util.markChunkDirty(this);
+ onFirstTick(isServerSide);
+ }
+ if (!isDead()) onPreTick(mTimer, isServerSide);
+ if (!isDead()) {
+ mTimer++;
+ super.updateEntity();
+ }
+ if (!isServerSide) {
+ if (mNeedsUpdate) {
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ //worldObj.func_147479_m(xCoord, yCoord, zCoord);
+ mNeedsUpdate = false;
+ }
+ }
+ if (!isDead()) onTick(mTimer, isServerSide);
+ if (!isDead() && isServerSide && mTimer > 2 && mSendClientData) {
+ sendClientData(null);
+ }
+ if (!isDead()) onPostTick(mTimer, isServerSide);
+
+ } catch (Throwable e) {
+ GT_FML_LOGGER.error("UpdateEntity Failed", e);
+ e.printStackTrace(GT_Log.err);
+ try {
+ onTickFailed(mTimer, isServerSide);
+ } catch (Throwable e2) {
+ GT_FML_LOGGER.error("UpdateEntity:onTickFailed Failed", e);
+ }
+ }
+
+ mIsRunningTick = false;
+ }
+
+ @Override
+ public void sendClientData(EntityPlayerMP aPlayer) {
+ if (mSendClientData) {
+ GT_FML_LOGGER.info("Sending client data");
+ super.sendClientData(aPlayer);
+ mSendClientData = false;
+ }
+ }
+
+ /** The very first Tick happening to this TileEntity */
+ public void onFirstTick(boolean isServerSide) {
+ if (isServerSide) {
+ checkDropCover();
+ } else {
+ requestCoverDataIfNeeded();
+ }
+ }
+
+ /** The first part of the Tick. */
+ public void onPreTick(long aTick, boolean isServerSide) { /*Do nothing*/ }
+
+ /** The regular Tick. */
+ public void onTick(long aTimer, boolean isServerSide) { /*Do nothing*/ }
+
+ /** The absolute last part of the Tick. */
+ public void onPostTick(long aTick, boolean isServerSide) { /*Do nothing*/ }
+
+ /** Gets called when there is an Exception happening during one of the Tick Functions. */
+ public void onTickFailed(long aTimer, boolean isServerSide) { /*Do nothing*/ }
+
+ @Override
+ public void onNeighborBlockChange(World aWorld, Block aBlock) {
+ mBlockUpdated = true;
+ }
+
+ @Override
+ public void issueClientUpdate() {
+ mSendClientData = true;
+ }
+
+ @Override
+ public byte getComparatorValue(byte aSide) {
+ return 0;
+ }
+
+}