diff options
Diffstat (limited to 'src/main/java/gregtech/api/multitileentity/base')
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; + } + +} |