package gregtech.api.multitileentity.base; 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; import static gregtech.api.enums.GT_Values.emptyIconContainerArray; import java.util.ArrayList; import java.util.List; import java.util.UUID; 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.ChunkCoordinates; 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 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.enums.Textures; import gregtech.api.gui.modularui.GT_UIInfos; import gregtech.api.interfaces.IIconContainer; 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.MultiTileEntityBlockInternal; import gregtech.api.multitileentity.MultiTileEntityClassContainer; import gregtech.api.multitileentity.MultiTileEntityRegistry; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.multitileentity.multiblock.casing.InventoryUpgrade; import gregtech.api.net.GT_Packet_MultiTileEntity; import gregtech.api.net.GT_Packet_New; import gregtech.api.objects.GT_ItemStack; import gregtech.api.objects.XSTR; import gregtech.api.render.TextureFactory; 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.common.render.GT_MultiTexture; import gregtech.common.render.IRenderedBlock; public abstract class BaseMultiTileEntity extends CoverableTileEntity implements IMultiTileEntity, IHasWorldObjectAndCoords, IRenderedBlock, IGregtechWailaProvider { public IIconContainer[] mTextures = emptyIconContainerArray; // public IIconContainer[] mTexturesFront = emptyIconContainerArray; // 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 // 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 mShouldRefresh = true; 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; protected int mRGBa = GT_Values.UNCOLORED; 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 loadTextureNBT(NBTTagCompound aNBT) { // Loading the registry final String textureName = aNBT.getString(NBT.TEXTURE); mTextures = new IIconContainer[] { new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/bottom"), new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/top"), new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/side"), }; } @Override public void copyTextures() { // Loading an instance final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); if (tCanonicalTileEntity instanceof BaseMultiTileEntity) mTextures = ((BaseMultiTileEntity) tCanonicalTileEntity).mTextures; } @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)); if (aNBT.hasKey(NBT.COLOR)) mRGBa = aNBT.getInteger(NBT.COLOR); 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 (GregTech_API.sBlockIcons == null && aNBT.hasKey(NBT.TEXTURE)) { loadTextureNBT(aNBT); } else { copyTextures(); } 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 boolean useModularUI() { return false; } @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) { return new ITexture[] { GT_MultiTexture.get(textureUncovered), coverTexture }; } else { return textureUncovered; } } @Override public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { // Top, bottom or side aSide = (byte) Math.min(aSide, 2); return new ITexture[] { TextureFactory.of(mTextures[aSide], GT_Util.getRGBaArray(mRGBa)) }; } @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 this.mRGBa; } @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) { GT_FML_LOGGER.error("onBlockActivated Failed", 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 (!getCoverInfoAtSide(aSide).isGUIClickable()) 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 (!getCoverInfoAtSide(aSide).isGUIClickable()) return false; return openModularUi(aPlayer, aSide); } } return false; } public boolean hasGui(byte aSide) { return false; } boolean openModularUi(EntityPlayer aPlayer, byte aSide) { if (!hasGui(aSide) || !isServerSide()) { System.out.println("No GUI or Not Serverside"); return false; } GT_UIInfos.openGTTileEntityUI(this, aPlayer); System.out.println("Trying to open a UI"); return true; } 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()))); onBaseTEDestroyed(); 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; } /** * @return a Packet containing all Data which has to be synchronised to the Client - Override as needed */ public GT_Packet_New getClientDataPacket() { final GT_Packet_MultiTileEntity packet = new GT_Packet_MultiTileEntity( 0, xCoord, (short) yCoord, zCoord, getMultiTileEntityRegistryID(), getMultiTileEntityID(), (byte) ((mFacing & 7) | (mRedstone ? 16 : 0)), mColor); packet.setCoverData( getCoverInfoAtSide((byte) 0).getCoverID(), getCoverInfoAtSide((byte) 1).getCoverID(), getCoverInfoAtSide((byte) 2).getCoverID(), getCoverInfoAtSide((byte) 3).getCoverID(), getCoverInfoAtSide((byte) 4).getCoverID(), getCoverInfoAtSide((byte) 5).getCoverID()); packet.setRedstoneData( (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))); if (this instanceof IMTE_HasModes) { final IMTE_HasModes mteModes = (IMTE_HasModes) this; packet.setModes(mteModes.getMode(), mteModes.getAllowedModes()); } if (this instanceof IMultiBlockPart) { final IMultiBlockPart mtePart = (IMultiBlockPart) this; if (mtePart.getTargetPos() != null) { final ChunkCoordinates aTarget = mtePart.getTargetPos(); packet.setTargetPos(aTarget.posX, (short) aTarget.posY, aTarget.posZ); } packet.setInventoryIndex(mtePart.getLockedInventoryIndex()); } if (this instanceof InventoryUpgrade) { String tName = ((InventoryUpgrade) this).getInventoryName(); packet.setInventoryName(tName); } return packet; } @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(); } @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: // Nothing here, currently 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 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 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() { System.out.println("Open Inventory"); /* Do nothing */ } @Override public void closeInventory() { System.out.println("Close Inventory"); /* 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 getCoverInfoAtSide(aSide).letsFluidIn(aFluid); } public boolean coverLetsFluidOut(byte aSide, Fluid aFluid) { return getCoverInfoAtSide(aSide).letsFluidOut(aFluid); } public boolean coverLetsEnergyIn(byte aSide) { return getCoverInfoAtSide(aSide).letsEnergyIn(); } public boolean coverLetsEnergyOut(byte aSide) { return getCoverInfoAtSide(aSide).letsEnergyOut(); } public boolean coverLetsItemsIn(byte aSide, int aSlot) { return getCoverInfoAtSide(aSide).letsItemsIn(aSlot); } public boolean coverLetsItemsOut(byte aSide, int aSlot) { return getCoverInfoAtSide(aSide).letsItemsOut(aSlot); } @Override public ItemStack getStackForm(long aAmount) { return new ItemStack(Item.getItemById(getMultiTileEntityRegistryID()), (int) aAmount, getMultiTileEntityID()); } }