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.enums.SoundResource; 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 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 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 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 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. *

* 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 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 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, SoundResource.IC2_TOOLS_WRENCH, 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, SoundResource.RANDOM_BREAK, 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, SoundResource.IC2_TOOLS_WRENCH, 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, SoundResource.IC2_TOOLS_WRENCH, 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 getDrops(int aFortune, boolean aSilkTouch) { final ArrayList 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 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 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 getDebugInfo(EntityPlayer aPlayer, int aLogLevel) { final ArrayList 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 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); } }